diff options
author | Sam Leffler <sam@FreeBSD.org> | 2009-03-02 02:29:17 +0000 |
---|---|---|
committer | Sam Leffler <sam@FreeBSD.org> | 2009-03-02 02:29:17 +0000 |
commit | 4e623cd134236f71ad45def5bce32c4b781da174 (patch) | |
tree | fdef898b1a2d04c7e3c2b8c50dd9d9d200b6a9e1 | |
parent | 7a77de1cacae423db0feafcd5fdefd40b733a489 (diff) |
don't need these any more; we are now using a combined tree
Notes
Notes:
svn path=/head/; revision=189264
400 files changed, 0 insertions, 165860 deletions
diff --git a/contrib/hostapd/COPYING b/contrib/hostapd/COPYING deleted file mode 100644 index 14f5453722a8..000000000000 --- a/contrib/hostapd/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. - - <one line to give the program's name and a brief idea of what it does.> - Copyright (C) 19yy <name of author> - - 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. - - <signature of Ty Coon>, 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/contrib/hostapd/ChangeLog b/contrib/hostapd/ChangeLog deleted file mode 100644 index ab28973f9bba..000000000000 --- a/contrib/hostapd/ChangeLog +++ /dev/null @@ -1,431 +0,0 @@ -ChangeLog for hostapd - -2008-02-19 - v0.5.10 - * fixed EAP-SIM and EAP-AKA message parser to validate attribute - lengths properly to avoid potential crash caused by invalid messages - * fixed Reassociation Response callback processing when using internal - MLME (driver_{hostap,devicescape,test}.c) - * 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 Start response processing for fast reauthentication - case - * copy optional Proxy-State attributes into RADIUS response when acting - as a RADIUS authentication server - -2007-12-02 - v0.5.9 - * updated EAP Generalized Pre-Shared Key (EAP-GPSK) to use the latest - draft (draft-ietf-emu-eap-gpsk-07.txt) - * fixed debugging code not to use potentially unaligned read to fetch - IPv4 addresses - -2007-05-28 - v0.5.8 - * updated driver_devicescape.c to build with the current - wireless-dev.git tree and net/d80211 changes - * updated EAP Generalized Pre-Shared Key (EAP-GPSK) to use the latest - draft (draft-ietf-emu-eap-gpsk-03.txt) - * 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 - * RADIUS server: added support for processing duplicate messages - (retransmissions from RADIUS client) by replying with the previous - reply - -2006-12-31 - v0.5.7 - * 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 - -2006-11-24 - v0.5.6 - * added support for configuring and controlling multiple BSSes per - radio interface (bss=<ifname> 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 <addr>' 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<pid file> 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 <addr>') - * 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/contrib/hostapd/FREEBSD-Xlist b/contrib/hostapd/FREEBSD-Xlist deleted file mode 100644 index 1f544522a1b5..000000000000 --- a/contrib/hostapd/FREEBSD-Xlist +++ /dev/null @@ -1,17 +0,0 @@ -$FreeBSD$ -.cvsignore -driver.c -driver_bsd.c -driver_devicescape.c -driver_madwifi.c -driver_prism54.c -l2_packet_freebsd.c -l2_packet_linux.c -l2_packet_ndis.c -l2_packet_pcap.c -l2_packet_winpcap.c -nt_password_hash.c -os_win32.c -prism54.h -priv_netlink.h -wireless_copy.h diff --git a/contrib/hostapd/FREEBSD-upgrade b/contrib/hostapd/FREEBSD-upgrade deleted file mode 100644 index 08922051fe55..000000000000 --- a/contrib/hostapd/FREEBSD-upgrade +++ /dev/null @@ -1,24 +0,0 @@ -$FreeBSD$ - -WPA/802.1x Authenticator - originals can be found at: http://hostap.epitest.fi/releases/ - - -For the import files and directories were pruned by: - - tar -X FREEBSD-Xlist -zxf hostapd-0.5.8.tar.gz - -then imported by: - - cvs import -m 'Import of hostapd 0.5.8' \ - src/contrib/hostapd MALINEN v0_5_8 - -To make local changes to hostapd, simply patch and commit to the -main branch (aka HEAD). Never make local changes on the vendor -(MALINEN) branch. - -All local changes should be submitted to Jouni Malinen for inclusion in -the next vendor release. - -sam@FreeBSD.org -7-July-2007 diff --git a/contrib/hostapd/Makefile b/contrib/hostapd/Makefile deleted file mode 100644 index 4fadede02057..000000000000 --- a/contrib/hostapd/Makefile +++ /dev/null @@ -1,444 +0,0 @@ -CC=gcc -DIR_WPA_SUPPLICANT=. - -ifndef CFLAGS -CFLAGS = -MMD -O2 -Wall -g -endif - -# 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 - -# Include directories for CVS version -CFLAGS += -I. -I../utils -I$(DIR_WPA_SUPPLICANT) - -# 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 = hostapd.o eloop.o ieee802_1x.o eapol_sm.o radius.o md5.o rc4.o md4.o \ - common.o ieee802_11.o config.o ieee802_11_auth.o accounting.o \ - sta_info.o radius_client.o sha1.o wpa.o aes_wrap.o ctrl_iface.o \ - driver_conf.o os_$(CONFIG_OS).o preauth.o pmksa_cache.o beacon.o \ - hw_features.o wme.o ap_list.o reconfig.o \ - mlme.o vlan_init.o ieee802_11h.o - -HOBJS=hlr_auc_gw.o common.o os_$(CONFIG_OS).o milenage.o aes_wrap.o - -CFLAGS += -DCONFIG_CTRL_IFACE -DCONFIG_CTRL_IFACE_UNIX - -ifdef CONFIG_IAPP -CFLAGS += -DCONFIG_IAPP -OBJS += iapp.o -endif - -ifdef CONFIG_RSN_PREAUTH -CFLAGS += -DCONFIG_RSN_PREAUTH -CONFIG_L2_PACKET=y -endif - -ifdef CONFIG_PEERKEY -CFLAGS += -DCONFIG_PEERKEY -endif - -ifdef CONFIG_IEEE80211W -CFLAGS += -DCONFIG_IEEE80211W -NEED_SHA256=y -endif - -ifdef CONFIG_DRIVER_HOSTAP -CFLAGS += -DCONFIG_DRIVER_HOSTAP -OBJS += driver.o -endif - -ifdef CONFIG_DRIVER_WIRED -CFLAGS += -DCONFIG_DRIVER_WIRED -OBJS += driver_wired.o -endif - -ifdef CONFIG_DRIVER_MADWIFI -CFLAGS += -DCONFIG_DRIVER_MADWIFI -OBJS += driver_madwifi.o -CONFIG_L2_PACKET=y -endif - -ifdef CONFIG_DRIVER_PRISM54 -CFLAGS += -DCONFIG_DRIVER_PRISM54 -OBJS += driver_prism54.o -endif - -ifdef CONFIG_DRIVER_DEVICESCAPE -CFLAGS += -DCONFIG_DRIVER_DEVICESCAPE -OBJS += driver_devicescape.o -endif - -ifdef CONFIG_DRIVER_BSD -CFLAGS += -DCONFIG_DRIVER_BSD -OBJS += driver_bsd.o -CONFIG_L2_PACKET=y -CONFIG_DNET_PCAP=y -CONFIG_L2_FREEBSD=y -endif - -ifdef CONFIG_DRIVER_TEST -CFLAGS += -DCONFIG_DRIVER_TEST -OBJS += driver_test.o -endif - -ifdef CONFIG_L2_PACKET -ifdef CONFIG_DNET_PCAP -ifdef CONFIG_L2_FREEBSD -LIBS += -lpcap -OBJS += $(DIR_WPA_SUPPLICANT)/l2_packet_freebsd.o -else -LIBS += -ldnet -lpcap -OBJS += $(DIR_WPA_SUPPLICANT)/l2_packet_pcap.o -endif -else -OBJS += $(DIR_WPA_SUPPLICANT)/l2_packet_linux.o -endif -endif - - -ifdef CONFIG_EAP_MD5 -CFLAGS += -DEAP_MD5 -OBJS += eap_md5.o -endif - -ifdef CONFIG_EAP_TLS -CFLAGS += -DEAP_TLS -OBJS += eap_tls.o -TLS_FUNCS=y -endif - -ifdef CONFIG_EAP_PEAP -CFLAGS += -DEAP_PEAP -OBJS += eap_peap.o -TLS_FUNCS=y -CONFIG_EAP_TLV=y -CONFIG_EAP_MSCHAPV2=y -endif - -ifdef CONFIG_EAP_TTLS -CFLAGS += -DEAP_TTLS -OBJS += eap_ttls.o -TLS_FUNCS=y -endif - -ifdef CONFIG_EAP_MSCHAPV2 -CFLAGS += -DEAP_MSCHAPv2 -OBJS += eap_mschapv2.o -MS_FUNCS=y -endif - -ifdef CONFIG_EAP_GTC -CFLAGS += -DEAP_GTC -OBJS += eap_gtc.o -endif - -ifdef CONFIG_EAP_SIM -CFLAGS += -DEAP_SIM -OBJS += eap_sim.o -CONFIG_EAP_SIM_COMMON=y -endif - -ifdef CONFIG_EAP_AKA -CFLAGS += -DEAP_AKA -OBJS += eap_aka.o -CONFIG_EAP_SIM_COMMON=y -endif - -ifdef CONFIG_EAP_SIM_COMMON -OBJS += $(DIR_WPA_SUPPLICANT)/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 += eap_sim_db.o -endif - -ifdef CONFIG_EAP_PAX -CFLAGS += -DEAP_PAX -OBJS += eap_pax.o $(DIR_WPA_SUPPLICANT)/eap_pax_common.o -endif - -ifdef CONFIG_EAP_PSK -CFLAGS += -DEAP_PSK -OBJS += eap_psk.o $(DIR_WPA_SUPPLICANT)/eap_psk_common.o -endif - -ifdef CONFIG_EAP_SAKE -CFLAGS += -DEAP_SAKE -OBJS += eap_sake.o $(DIR_WPA_SUPPLICANT)/eap_sake_common.o -endif - -ifdef CONFIG_EAP_GPSK -CFLAGS += -DEAP_GPSK -OBJS += eap_gpsk.o $(DIR_WPA_SUPPLICANT)/eap_gpsk_common.o -ifdef CONFIG_EAP_GPSK_SHA256 -CFLAGS += -DEAP_GPSK_SHA256 -NEED_SHA256=y -endif -endif - -ifdef CONFIG_EAP_VENDOR_TEST -CFLAGS += -DEAP_VENDOR_TEST -OBJS += eap_vendor_test.o -endif - -ifdef CONFIG_EAP_TLV -CFLAGS += -DEAP_TLV -OBJS += eap_tlv.o -endif - -ifdef CONFIG_EAP -CFLAGS += -DEAP_SERVER -OBJS += eap.o eap_methods.o eap_identity.o -endif - -ifndef CONFIG_TLS -CONFIG_TLS=openssl -endif - -ifdef TLS_FUNCS -# Shared TLS functions (needed for EAP_TLS, EAP_PEAP, and EAP_TTLS) -CFLAGS += -DEAP_TLS_FUNCS -OBJS += eap_tls_common.o -ifeq ($(CONFIG_TLS), openssl) -OBJS += $(DIR_WPA_SUPPLICANT)/tls_openssl.o -LIBS += -lssl -lcrypto -LIBS_p += -lcrypto -LIBS_h += -lcrypto -endif -ifeq ($(CONFIG_TLS), gnutls) -OBJS += $(DIR_WPA_SUPPLICANT)/tls_gnutls.o -LIBS += -lgnutls -lgcrypt -lgpg-error -LIBS_p += -lgcrypt -LIBS_h += -lgcrypt -endif -ifdef CONFIG_GNUTLS_EXTRA -CFLAGS += -DCONFIG_GNUTLS_EXTRA -LIBS += -lgnutls-extra -endif -NEED_CRYPTO=y -else -OBJS += $(DIR_WPA_SUPPLICANT)/tls_none.o -endif - -ifdef CONFIG_PKCS12 -CFLAGS += -DPKCS12_FUNCS -endif - -ifdef MS_FUNCS -OBJS += $(DIR_WPA_SUPPLICANT)/ms_funcs.o -NEED_CRYPTO=y -endif - -ifdef NEED_CRYPTO -ifndef TLS_FUNCS -ifeq ($(CONFIG_TLS), openssl) -LIBS += -lcrypto -LIBS_p += -lcrypto -LIBS_h += -lcrypto -endif -ifeq ($(CONFIG_TLS), gnutls) -LIBS += -lgcrypt -LIBS_p += -lgcrypt -LIBS_h += -lgcrypt -endif -endif -ifeq ($(CONFIG_TLS), openssl) -OBJS += $(DIR_WPA_SUPPLICANT)/crypto.o -OBJS_p += $(DIR_WPA_SUPPLICANT)/crypto.o -HOBJS += $(DIR_WPA_SUPPLICANT)/crypto.o -CONFIG_INTERNAL_SHA256=y -endif -ifeq ($(CONFIG_TLS), gnutls) -OBJS += $(DIR_WPA_SUPPLICANT)/crypto_gnutls.o -OBJS_p += $(DIR_WPA_SUPPLICANT)/crypto_gnutls.o -HOBJS += $(DIR_WPA_SUPPLICANT)/crypto_gnutls.o -CONFIG_INTERNAL_SHA256=y -endif -else -CONFIG_INTERNAL_AES=y -CONFIG_INTERNAL_SHA1=y -CONFIG_INTERNAL_MD5=y -CONFIG_INTERNAL_SHA256=y -endif - -ifdef CONFIG_INTERNAL_AES -CFLAGS += -DINTERNAL_AES -endif -ifdef CONFIG_INTERNAL_SHA1 -CFLAGS += -DINTERNAL_SHA1 -endif -ifdef CONFIG_INTERNAL_SHA256 -CFLAGS += -DINTERNAL_SHA256 -endif -ifdef CONFIG_INTERNAL_MD5 -CFLAGS += -DINTERNAL_MD5 -endif -ifdef CONFIG_INTERNAL_MD4 -CFLAGS += -DINTERNAL_MD4 -endif - -ifdef NEED_SHA256 -OBJS += sha256.o -endif - -ifdef CONFIG_RADIUS_SERVER -CFLAGS += -DRADIUS_SERVER -OBJS += 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 - -ALL=hostapd hostapd_cli - -all: verify_config $(ALL) - -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 - for i in $(ALL); do cp $$i /usr/local/bin/$$i; done - -hostapd: $(OBJS) - $(CC) -o hostapd $(OBJS) $(LIBS) - -driver_conf.c: Makefile .config - rm -f driver_conf.c - echo '/* THIS FILE AUTOMATICALLY GENERATED, DO NOT EDIT! */' \ - > driver_conf.c - echo '#include "includes.h"' >> driver_conf.c - echo '#include "hostapd.h"' >> driver_conf.c - echo '#include "driver.h"' >> driver_conf.c -ifdef CONFIG_DRIVER_HOSTAP - echo "void hostap_driver_register(void);" >> driver_conf.c -endif -ifdef CONFIG_DRIVER_WIRED - echo "void wired_driver_register(void);" >> driver_conf.c -endif -ifdef CONFIG_DRIVER_MADWIFI - echo "void madwifi_driver_register(void);" >> driver_conf.c -endif -ifdef CONFIG_DRIVER_PRISM54 - echo "void prism54_driver_register(void);" >> driver_conf.c -endif -ifdef CONFIG_DRIVER_DEVICESCAPE - echo "void devicescape_driver_register(void);" >> driver_conf.c -endif -ifdef CONFIG_DRIVER_BSD - echo "void bsd_driver_register(void);" >> driver_conf.c -endif -ifdef CONFIG_DRIVER_TEST - echo "void test_driver_register(void);" >> driver_conf.c -endif - echo 'void register_drivers(void) {' >> driver_conf.c -ifdef CONFIG_DRIVER_HOSTAP - echo "hostap_driver_register();" >> driver_conf.c -endif -ifdef CONFIG_DRIVER_WIRED - echo "wired_driver_register();" >> driver_conf.c -endif -ifdef CONFIG_DRIVER_MADWIFI - echo "madwifi_driver_register();" >> driver_conf.c -endif -ifdef CONFIG_DRIVER_PRISM54 - echo "prism54_driver_register();" >> driver_conf.c -endif -ifdef CONFIG_DRIVER_DEVICESCAPE - echo "devicescape_driver_register();" >> driver_conf.c -endif -ifdef CONFIG_DRIVER_BSD - echo "bsd_driver_register();" >> driver_conf.c -endif -ifdef CONFIG_DRIVER_TEST - echo "test_driver_register();" >> driver_conf.c -endif - echo '}' >> driver_conf.c - -hostapd_cli: hostapd_cli.o $(DIR_WPA_SUPPLICANT)/wpa_ctrl.o - $(CC) -o hostapd_cli hostapd_cli.o $(DIR_WPA_SUPPLICANT)/wpa_ctrl.o - -NOBJS = nt_password_hash.o $(DIR_WPA_SUPPLICANT)/ms_funcs.o sha1.o rc4.o md5.o -NOBJS += $(DIR_WPA_SUPPLICANT)/crypto.o os_$(CONFIG_OS).o -ifdef TLS_FUNCS -LIBS_n += -lcrypto -endif - -nt_password_hash: $(NOBJS) - $(CC) -o nt_password_hash $(NOBJS) $(LIBS_n) - -hlr_auc_gw: $(HOBJS) - $(CC) -o hlr_auc_gw $(HOBJS) $(LIBS_h) - -clean: - rm -f core *~ *.o hostapd hostapd_cli nt_password_hash hlr_auc_gw - rm -f *.d driver_conf.c - -%.eps: %.fig - fig2dev -L eps $*.fig $*.eps - -%.png: %.fig - fig2dev -L png -m 3 $*.fig | pngtopnm | pnmscale 0.4 | pnmtopng \ - > $*.png - -docs-pics: doc/hostapd.png doc/hostapd.eps - -docs: docs-pics - doxygen doc/doxygen.full - $(MAKE) -C doc/latex - cp doc/latex/refman.pdf hostapd-devel.pdf - -docs-fast: docs-pics - doxygen doc/doxygen.fast - -clean-docs: - rm -rf doc/latex doc/html - rm -f doc/hosta.d{eps,png} hostapd-devel.pdf - -TEST_SRC_MILENAGE = milenage.c aes_wrap.c common.c os_$(CONFIG_OS).c -test-milenage: $(TEST_SRC_MILENAGE) - $(CC) -o test-milenage -Wall -Werror $(TEST_SRC_MILENAGE) \ - -DTEST_MAIN_MILENAGE -I. -I../wpa_supplicant -DINTERNAL_AES - ./test-milenage - rm test-milenage - --include $(OBJS:%.o=%.d) diff --git a/contrib/hostapd/README b/contrib/hostapd/README deleted file mode 100644 index dd242042d406..000000000000 --- a/contrib/hostapd/README +++ /dev/null @@ -1,386 +0,0 @@ -hostapd - user space IEEE 802.11 AP and IEEE 802.1X/WPA/WPA2/EAP - Authenticator and RADIUS authentication server -================================================================ - -Copyright (c) 2002-2008, Jouni Malinen <j@w1.fi> 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<path>) - - Prism54 driver for Intersil/Conexant Prism GT/Duette/Indigo - (http://www.prism54.org/) - - 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<TM> (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/contrib/hostapd/accounting.c b/contrib/hostapd/accounting.c deleted file mode 100644 index b22347b2ac2e..000000000000 --- a/contrib/hostapd/accounting.c +++ /dev/null @@ -1,467 +0,0 @@ -/* - * hostapd / RADIUS Accounting - * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 <assert.h> - -#include "hostapd.h" -#include "radius.h" -#include "radius_client.h" -#include "eloop.h" -#include "accounting.h" -#include "ieee802_1x.h" -#include "driver.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 - -/* from ieee802_1x.c */ -const char *radius_mode_txt(struct hostapd_data *hapd); -int radius_sta_rate(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)); - - 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, 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) { - snprintf(buf, sizeof(buf), RADIUS_ADDR_FORMAT, - MAC2STR(sta->addr)); - val = (u8 *) buf; - len = 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, - 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; - } - - 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, strlen(buf))) { - printf("Could not add Called-Station-Id\n"); - goto fail; - } - - if (sta) { - 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, 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; - } - - 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, 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); - 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_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); -} - - -void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta) -{ - struct radius_msg *msg; - int interval; - - if (sta->acct_session_started) - return; - - time(&sta->acct_session_start); - sta->last_rx_bytes = sta->last_tx_bytes = 0; - sta->acct_input_gigawords = sta->acct_output_gigawords = 0; - hostapd_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; -} - - -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; - 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; - } - - if (!radius_msg_add_attr_int32(msg, RADIUS_ATTR_ACCT_SESSION_TIME, - time(NULL) - 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, - time(NULL))) { - 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); - free(msg); -} - - -void accounting_sta_interim(struct hostapd_data *hapd, struct sta_info *sta) -{ - if (sta->acct_session_started) - accounting_sta_report(hapd, sta, 0); -} - - -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); - sta->acct_session_started = 0; - } -} - - -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; -} - - -/* Process the RADIUS frames from Accounting Server */ -static RadiusRxResult -accounting_receive(struct radius_msg *msg, struct radius_msg *req, - u8 *shared_secret, size_t shared_secret_len, void *data) -{ - if (msg->hdr->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); - free(msg); - return; - } - - radius_client_send(hapd->radius, msg, RADIUS_ACCT, NULL); -} - - -int accounting_init(struct hostapd_data *hapd) -{ - /* Acct-Session-Id should be unique over reboots. If reliable clock is - * not available, this could be replaced with reboot counter, etc. */ - hapd->acct_session_id_hi = time(NULL); - - if (radius_client_register(hapd->radius, RADIUS_ACCT, - accounting_receive, hapd)) - return -1; - - accounting_report_state(hapd, 1); - - return 0; -} - - -void accounting_deinit(struct hostapd_data *hapd) -{ - accounting_report_state(hapd, 0); -} - - -int accounting_reconfig(struct hostapd_data *hapd, - struct hostapd_config *oldconf) -{ - if (!hapd->radius_client_reconfigured) - return 0; - - accounting_deinit(hapd); - return accounting_init(hapd); -} diff --git a/contrib/hostapd/accounting.h b/contrib/hostapd/accounting.h deleted file mode 100644 index ee2ee64e3b02..000000000000 --- a/contrib/hostapd/accounting.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * hostapd / RADIUS Accounting - * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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_start(struct hostapd_data *hapd, struct sta_info *sta); -void accounting_sta_interim(struct hostapd_data *hapd, struct sta_info *sta); -void accounting_sta_stop(struct hostapd_data *hapd, struct sta_info *sta); -void accounting_sta_get_id(struct hostapd_data *hapd, struct sta_info *sta); -int accounting_init(struct hostapd_data *hapd); -void accounting_deinit(struct hostapd_data *hapd); -int accounting_reconfig(struct hostapd_data *hapd, - struct hostapd_config *oldconf); - -#endif /* ACCOUNTING_H */ diff --git a/contrib/hostapd/aes.c b/contrib/hostapd/aes.c deleted file mode 100644 index 1a2459b3e013..000000000000 --- a/contrib/hostapd/aes.c +++ /dev/null @@ -1,1107 +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 <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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" - -/* - * rijndael-alg-fst.c - * - * @version 3.0 (December 2000) - * - * Optimised ANSI C code for the Rijndael cipher (now AES) - * - * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be> - * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be> - * @author Paulo Barreto <paulo.barreto@terra.com.br> - * - * 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. - */ - -/* #define FULL_UNROLL */ -#define AES_SMALL_TABLES - - -/* -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]; -*/ - -static 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 -static 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, -}; -static 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, -}; -static 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, -}; -static 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 */ -static 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 -static 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, -}; -static 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, -}; -static 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, -}; -static 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, -}; -static 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 */ -static 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, -}; -static 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 */ - - -#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 */ - -#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) - -#ifdef _MSC_VER -#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 - -/** - * 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; - } -} - -/** - * 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 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 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); -} - - - -/* Generic wrapper functions for AES functions */ - -void * aes_encrypt_init(const u8 *key, size_t len) -{ - u32 *rk; - if (len != 16) - return NULL; - rk = os_malloc(4 * 44); - 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_free(ctx); -} - - -void * aes_decrypt_init(const u8 *key, size_t len) -{ - u32 *rk; - if (len != 16) - return NULL; - rk = os_malloc(4 * 44); - if (rk == NULL) - return NULL; - rijndaelKeySetupDec(rk, key); - return rk; -} - - -void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) -{ - rijndaelDecrypt(ctx, crypt, plain); -} - - -void aes_decrypt_deinit(void *ctx) -{ - os_free(ctx); -} diff --git a/contrib/hostapd/aes.h b/contrib/hostapd/aes.h deleted file mode 100644 index 6b9f4147afb1..000000000000 --- a/contrib/hostapd/aes.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * AES functions - * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 - -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/contrib/hostapd/aes_wrap.c b/contrib/hostapd/aes_wrap.c deleted file mode 100644 index 765b1ca871ad..000000000000 --- a/contrib/hostapd/aes_wrap.c +++ /dev/null @@ -1,515 +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 <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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_wrap.h" -#include "crypto.h" - -#ifdef INTERNAL_AES -#include "aes.c" -#endif /* INTERNAL_AES */ - - -#ifndef CONFIG_NO_AES_WRAP - -/** - * 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; -} - -#endif /* CONFIG_NO_AES_WRAP */ - - -/** - * 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; -} - - -#define BLOCK_SIZE 16 - -#ifndef CONFIG_NO_AES_OMAC1 - -static void gf_mulx(u8 *pad) -{ - int i, carry; - - carry = pad[0] & 0x80; - for (i = 0; i < BLOCK_SIZE - 1; i++) - pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7); - pad[BLOCK_SIZE - 1] <<= 1; - if (carry) - pad[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 - */ -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[BLOCK_SIZE], pad[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, 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 >= BLOCK_SIZE) { - for (i = 0; i < BLOCK_SIZE; i++) { - cbc[i] ^= *pos++; - if (pos >= end) { - e++; - pos = addr[e]; - end = pos + len[e]; - } - } - if (left > BLOCK_SIZE) - aes_encrypt(ctx, cbc, cbc); - left -= BLOCK_SIZE; - } - - os_memset(pad, 0, 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 < 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); -} - -#endif /* CONFIG_NO_AES_OMAC1 */ - - -/** - * 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; -} - - -#ifndef CONFIG_NO_AES_CTR - -/** - * 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[BLOCK_SIZE], buf[BLOCK_SIZE]; - - ctx = aes_encrypt_init(key, 16); - if (ctx == NULL) - return -1; - os_memcpy(counter, nonce, BLOCK_SIZE); - - while (left > 0) { - aes_encrypt(ctx, counter, buf); - - len = (left < BLOCK_SIZE) ? left : BLOCK_SIZE; - for (j = 0; j < len; j++) - pos[j] ^= buf[j]; - pos += len; - left -= len; - - for (i = BLOCK_SIZE - 1; i >= 0; i--) { - counter[i]++; - if (counter[i]) - break; - } - } - aes_encrypt_deinit(ctx); - return 0; -} - -#endif /* CONFIG_NO_AES_CTR */ - - -#ifndef CONFIG_NO_AES_EAX - -/** - * 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[BLOCK_SIZE], hdr_mac[BLOCK_SIZE], data_mac[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); - omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac); - - buf[15] = 1; - os_memcpy(buf + 16, hdr, hdr_len); - omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac); - - aes_128_ctr_encrypt(key, nonce_mac, data, data_len); - buf[15] = 2; - os_memcpy(buf + 16, data, data_len); - omac1_aes_128(key, buf, 16 + data_len, data_mac); - - os_free(buf); - - for (i = 0; i < BLOCK_SIZE; i++) - tag[i] = nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i]; - - return 0; -} - - -/** - * 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[BLOCK_SIZE], hdr_mac[BLOCK_SIZE], data_mac[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); - omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac); - - buf[15] = 1; - os_memcpy(buf + 16, hdr, hdr_len); - omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac); - - buf[15] = 2; - os_memcpy(buf + 16, data, data_len); - omac1_aes_128(key, buf, 16 + data_len, data_mac); - - os_free(buf); - - for (i = 0; i < BLOCK_SIZE; i++) { - if (tag[i] != (nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i])) - return -2; - } - - aes_128_ctr_encrypt(key, nonce_mac, data, data_len); - - return 0; -} - -#endif /* CONFIG_NO_AES_EAX */ - - -#ifndef CONFIG_NO_AES_CBC - -/** - * 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[BLOCK_SIZE]; - u8 *pos = data; - int i, j, blocks; - - ctx = aes_encrypt_init(key, 16); - if (ctx == NULL) - return -1; - os_memcpy(cbc, iv, BLOCK_SIZE); - - blocks = data_len / BLOCK_SIZE; - for (i = 0; i < blocks; i++) { - for (j = 0; j < BLOCK_SIZE; j++) - cbc[j] ^= pos[j]; - aes_encrypt(ctx, cbc, cbc); - os_memcpy(pos, cbc, BLOCK_SIZE); - pos += 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[BLOCK_SIZE], tmp[BLOCK_SIZE]; - u8 *pos = data; - int i, j, blocks; - - ctx = aes_decrypt_init(key, 16); - if (ctx == NULL) - return -1; - os_memcpy(cbc, iv, BLOCK_SIZE); - - blocks = data_len / BLOCK_SIZE; - for (i = 0; i < blocks; i++) { - os_memcpy(tmp, pos, BLOCK_SIZE); - aes_decrypt(ctx, pos, pos); - for (j = 0; j < BLOCK_SIZE; j++) - pos[j] ^= cbc[j]; - os_memcpy(cbc, tmp, BLOCK_SIZE); - pos += BLOCK_SIZE; - } - aes_decrypt_deinit(ctx); - return 0; -} - -#endif /* CONFIG_NO_AES_CBC */ diff --git a/contrib/hostapd/aes_wrap.h b/contrib/hostapd/aes_wrap.h deleted file mode 100644 index 5eb4342a5bf9..000000000000 --- a/contrib/hostapd/aes_wrap.h +++ /dev/null @@ -1,44 +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 <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher); -int aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain); -int omac1_aes_128_vector(const u8 *key, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac); -int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac); -int aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out); -int aes_128_ctr_encrypt(const u8 *key, const u8 *nonce, - u8 *data, size_t data_len); -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); -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); -int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, - size_t data_len); -int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, - size_t data_len); - -#endif /* AES_WRAP_H */ diff --git a/contrib/hostapd/ap.h b/contrib/hostapd/ap.h deleted file mode 100644 index b73c5b47a6fb..000000000000 --- a/contrib/hostapd/ap.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * hostapd / Station table data structures - * Copyright (c) 2002-2004, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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_H -#define AP_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_WME BIT(9) -#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; - 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; - - 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; -}; - - -/* Maximum number of AIDs to use for STAs; must be 2007 or lower - * (8802.11 limitation) */ -#define MAX_AID_TABLE_SIZE 128 - -#define STA_HASH_SIZE 256 -#define STA_HASH(sta) (sta[5]) - - -/* 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) - -#endif /* AP_H */ diff --git a/contrib/hostapd/ap_list.c b/contrib/hostapd/ap_list.c deleted file mode 100644 index f2d322125fc8..000000000000 --- a/contrib/hostapd/ap_list.c +++ /dev/null @@ -1,459 +0,0 @@ -/* - * hostapd / AP table - * Copyright 2002-2003, Jouni Malinen <j@w1.fi> - * Copyright 2003-2004, Instant802 Networks, Inc. - * Copyright 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 "includes.h" - -#include "hostapd.h" -#include "ieee802_11.h" -#include "eloop.h" -#include "ap_list.h" -#include "hw_features.h" -#include "beacon.h" - - -struct ieee80211_frame_info { - u32 version; - u32 length; - u64 mactime; - u64 hosttime; - u32 phytype; - u32 channel; - u32 datarate; - u32 antenna; - u32 priority; - u32 ssi_type; - u32 ssi_signal; - u32 ssi_noise; - u32 preamble; - u32 encoding; - - /* Note: this structure is otherwise identical to capture format used - * in linux-wlan-ng, but this additional field is used to provide meta - * data about the frame to hostapd. This was the easiest method for - * providing this information, but this might change in the future. */ - u32 msg_type; -} __attribute__ ((packed)); - - -enum ieee80211_phytype { - ieee80211_phytype_fhss_dot11_97 = 1, - ieee80211_phytype_dsss_dot11_97 = 2, - ieee80211_phytype_irbaseband = 3, - ieee80211_phytype_dsss_dot11_b = 4, - ieee80211_phytype_pbcc_dot11_b = 5, - ieee80211_phytype_ofdm_dot11_g = 6, - ieee80211_phytype_pbcc_dot11_g = 7, - ieee80211_phytype_ofdm_dot11_a = 8, - ieee80211_phytype_dsss_dot11_turbog = 255, - ieee80211_phytype_dsss_dot11_turbo = 256, -}; - - -/* 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 void ap_list_new_ap(struct hostapd_iface *iface, struct ap_info *ap) -{ - wpa_printf(MSG_DEBUG, "New AP detected: " MACSTR, MAC2STR(ap->addr)); - - /* TODO: could send a notification message to an external program that - * would then determine whether a rogue AP has been detected */ -} - - -static void ap_list_expired_ap(struct hostapd_iface *iface, struct ap_info *ap) -{ - wpa_printf(MSG_DEBUG, "AP info expired: " MACSTR, MAC2STR(ap->addr)); - - /* TODO: could send a notification message to an external program */ -} - - -static int ap_list_beacon_olbc(struct hostapd_iface *iface, struct ap_info *ap) -{ - int i; - - if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G || - ap->phytype != ieee80211_phytype_pbcc_dot11_g || - 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, u8 *ap) -{ - struct ap_info *s; - - s = iface->ap_hash[STA_HASH(ap)]; - while (s != NULL && 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 (memcmp(s->addr, ap->addr, ETH_ALEN) == 0) { - iface->ap_hash[STA_HASH(ap->addr)] = s->hnext; - return; - } - - while (s->hnext != NULL && - 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--; - 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, u8 *addr) -{ - struct ap_info *ap; - - ap = wpa_zalloc(sizeof(struct ap_info)); - if (ap == NULL) - return NULL; - - /* initialize AP info data */ - 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)); - if (iface->conf->passive_scan_interval > 0) - ap_list_expired_ap(iface, ap->prev); - ap_free_ap(iface, ap->prev); - } - - return ap; -} - - -void ap_list_process_beacon(struct hostapd_iface *iface, - struct ieee80211_mgmt *mgmt, - struct ieee802_11_elems *elems, - struct hostapd_frame_info *fi) -{ - struct ap_info *ap; - int new_ap = 0; - size_t len; - - 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; - memcpy(ap->ssid, elems->ssid, len); - ap->ssid[len] = '\0'; - ap->ssid_len = len; - } - - 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; - 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; - 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; - - ap->num_beacons++; - time(&ap->last_beacon); - if (fi) { - ap->phytype = fi->phytype; - ap->ssi_signal = fi->ssi_signal; - ap->datarate = fi->datarate; - } - - if (new_ap) { - if (iface->conf->passive_scan_interval > 0) - ap_list_new_ap(iface, ap); - } else if (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)) { - struct hostapd_data *hapd = iface->bss[0]; - iface->olbc = 1; - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "OLBC AP detected: " MACSTR " - enable " - "protection\n", MAC2STR(ap->addr)); - ieee802_11_set_beacons(hapd->iface); - } -} - - -static void ap_list_timer(void *eloop_ctx, void *timeout_ctx) -{ - struct hostapd_iface *iface = eloop_ctx; - time_t now; - struct ap_info *ap; - - eloop_register_timeout(10, 0, ap_list_timer, iface, NULL); - - if (!iface->ap_list) - return; - - time(&now); - - /* FIX: it looks like jkm-Purina ended up in busy loop in this - * function. Apparently, something can still cause a loop in the AP - * list.. */ - - while (iface->ap_list) { - ap = iface->ap_list->prev; - if (ap->last_beacon + iface->conf->ap_table_expiration_time >= - now) - break; - - if (iface->conf->passive_scan_interval > 0) - ap_list_expired_ap(iface, ap); - ap_free_ap(iface, ap); - } - - if (iface->olbc) { - int olbc = 0; - ap = iface->ap_list; - while (ap) { - if (ap_list_beacon_olbc(iface, ap)) { - olbc = 1; - break; - } - ap = ap->next; - } - if (!olbc) { - struct hostapd_data *hapd = iface->bss[0]; - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "OLBC not detected anymore\n"); - iface->olbc = 0; - ieee802_11_set_beacons(hapd->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); -} - - -int ap_list_reconfig(struct hostapd_iface *iface, - struct hostapd_config *oldconf) -{ - time_t now; - struct ap_info *ap; - - if (iface->conf->ap_table_max_size == oldconf->ap_table_max_size && - iface->conf->ap_table_expiration_time == - oldconf->ap_table_expiration_time) - return 0; - - time(&now); - - while (iface->ap_list) { - ap = iface->ap_list->prev; - if (iface->num_ap <= iface->conf->ap_table_max_size && - ap->last_beacon + iface->conf->ap_table_expiration_time >= - now) - break; - - if (iface->conf->passive_scan_interval > 0) - ap_list_expired_ap(iface, iface->ap_list->prev); - ap_free_ap(iface, iface->ap_list->prev); - } - - return 0; -} diff --git a/contrib/hostapd/ap_list.h b/contrib/hostapd/ap_list.h deleted file mode 100644 index 668d9096341c..000000000000 --- a/contrib/hostapd/ap_list.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * hostapd / AP table - * Copyright 2002-2003, Jouni Malinen <j@w1.fi> - * Copyright 2003-2004, Instant802 Networks, Inc. - * Copyright 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 phytype; /* .11a / .11b / .11g / Atheros Turbo */ - int channel; - int datarate; /* in 100 kbps */ - int ssi_signal; - - unsigned int num_beacons; /* number of beacon frames received */ - 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, 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, - struct ieee80211_mgmt *mgmt, - struct ieee802_11_elems *elems, - struct hostapd_frame_info *fi); -int ap_list_init(struct hostapd_iface *iface); -void ap_list_deinit(struct hostapd_iface *iface); -int ap_list_reconfig(struct hostapd_iface *iface, - struct hostapd_config *oldconf); - -#endif /* AP_LIST_H */ diff --git a/contrib/hostapd/beacon.c b/contrib/hostapd/beacon.c deleted file mode 100644 index 7af2bc1754e2..000000000000 --- a/contrib/hostapd/beacon.c +++ /dev/null @@ -1,419 +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. - */ - -#include "includes.h" - -#ifndef CONFIG_NATIVE_WINDOWS - -#include "hostapd.h" -#include "ieee802_11.h" -#include "wpa.h" -#include "wme.h" -#include "beacon.h" -#include "hw_features.h" -#include "driver.h" -#include "sta_info.h" -#include "ieee802_11h.h" - - -static u8 ieee802_11_erp_info(struct hostapd_data *hapd) -{ - u8 erp = 0; - - if (hapd->iface == NULL || 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) - 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 == NULL || 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(struct hostapd_data *hapd, u8 *eid, - int max_len) -{ - int left; - u8 *pos = eid; - - if ((!hapd->iconf->ieee80211d && !hapd->iface->dfs_enable) || - max_len < 6) - return eid; - - *pos++ = WLAN_EID_COUNTRY; - pos++; /* length will be set later */ - memcpy(pos, hapd->iconf->country, 3); /* e.g., 'US ' */ - pos += 3; - left = max_len - 3; - - if ((pos - eid) & 1) { - if (left < 1) - return eid; - *pos++ = 0; /* pad for 16-bit alignment */ - left--; - } - - eid[1] = (pos - eid) - 2; - - return pos; -} - - -static u8 * hostapd_eid_power_constraint(struct hostapd_data *hapd, u8 *eid) - -{ - if (!hapd->iface->dfs_enable) - return eid; - *eid++ = WLAN_EID_PWR_CONSTRAINT; - *eid++ = 1; - *eid++ = hapd->iface->pwr_const; - return eid; -} - - -static u8 * hostapd_eid_tpc_report(struct hostapd_data *hapd, u8 *eid) - -{ - if (!hapd->iface->dfs_enable) - return eid; - *eid++ = WLAN_EID_TPC_REPORT; - *eid++ = 2; - *eid++ = hapd->iface->tx_power; /* TX POWER */ - *eid++ = 0; /* Link Margin */ - return eid; -} - -static u8 * hostapd_eid_channel_switch(struct hostapd_data *hapd, u8 *eid) - -{ - if (!hapd->iface->dfs_enable || !hapd->iface->channel_switch) - return eid; - *eid++ = WLAN_EID_CHANNEL_SWITCH; - *eid++ = 3; - *eid++ = CHAN_SWITCH_MODE_QUIET; - *eid++ = hapd->iface->channel_switch; /* New channel */ - /* 0 - very soon; 1 - before next TBTT; num - after num beacons */ - *eid++ = 0; - return eid; -} - - -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; - - memcpy(eid, ie, ielen); - return eid + ielen; -} - - -void handle_probe_req(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt, - size_t len) -{ - struct ieee80211_mgmt *resp; - struct ieee802_11_elems elems; - char *ssid; - u8 *pos, *epos; - size_t ssid_len; - struct sta_info *sta = NULL; - - if (!hapd->iconf->send_probe_response) - return; - - if (ieee802_11_parse_elems(hapd, mgmt->u.probe_req.variable, - len - (IEEE80211_HDRLEN + - sizeof(mgmt->u.probe_req)), &elems, - 0) - == ParseFailed) { - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "Could not parse ProbeReq from " MACSTR "\n", - MAC2STR(mgmt->sa)); - return; - } - - ssid = NULL; - ssid_len = 0; - - if ((!elems.ssid || !elems.supp_rates)) { - printf("STA " MACSTR " sent probe request without SSID or " - "supported rates element\n", MAC2STR(mgmt->sa)); - return; - } - - if (hapd->conf->ignore_broadcast_ssid && elems.ssid_len == 0) { - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MSGDUMPS, - "Probe Request from " MACSTR " for broadcast " - "SSID ignored\n", MAC2STR(mgmt->sa)); - return; - } - - sta = ap_get_sta(hapd, mgmt->sa); - - if (elems.ssid_len == 0 || - (elems.ssid_len == hapd->conf->ssid.ssid_len && - 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 (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MSGDUMPS)) { - printf("Probe Request from " MACSTR " for foreign " - "SSID '", MAC2STR(mgmt->sa)); - ieee802_11_print_ssid(elems.ssid, elems.ssid_len); - printf("'\n"); - } - return; - } - - /* TODO: verify that supp_rates contains at least one matching rate - * with AP configuration */ -#define MAX_PROBERESP_LEN 512 - resp = wpa_zalloc(MAX_PROBERESP_LEN); - if (resp == NULL) - return; - epos = ((u8 *) resp) + MAX_PROBERESP_LEN; - - resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_PROBE_RESP); - memcpy(resp->da, mgmt->sa, ETH_ALEN); - memcpy(resp->sa, hapd->own_addr, ETH_ALEN); - - 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; - 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); - - pos = hostapd_eid_power_constraint(hapd, pos); - pos = hostapd_eid_tpc_report(hapd, pos); - - /* ERP Information element */ - pos = hostapd_eid_erp_info(hapd, pos); - - /* Extended supported rates */ - pos = hostapd_eid_ext_supp_rates(hapd, pos); - - pos = hostapd_eid_wpa(hapd, pos, epos - pos, sta); - - /* Wi-Fi Wireless Multimedia Extensions */ - if (hapd->conf->wme_enabled) - pos = hostapd_eid_wme(hapd, pos); - - if (hostapd_send_mgmt_frame(hapd, resp, pos - (u8 *) resp, 0) < 0) - perror("handle_probe_req: send"); - - free(resp); - - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MSGDUMPS, "STA " MACSTR - " sent probe request for %s SSID\n", - 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; - int preamble; - u16 capab_info; - size_t head_len, tail_len; - int cts_protection = ((ieee802_11_erp_info(hapd) & - ERP_INFO_USE_PROTECTION) ? 1 : 0); - -#define BEACON_HEAD_BUF_SIZE 256 -#define BEACON_TAIL_BUF_SIZE 256 - head = wpa_zalloc(BEACON_HEAD_BUF_SIZE); - tailpos = tail = malloc(BEACON_TAIL_BUF_SIZE); - if (head == NULL || tail == NULL) { - printf("Failed to set beacon data\n"); - free(head); - free(tail); - return; - } - - head->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_BEACON); - head->duration = host_to_le16(0); - memset(head->da, 0xff, ETH_ALEN); - - memcpy(head->sa, hapd->own_addr, ETH_ALEN); - 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; - 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; - 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); - - tailpos = hostapd_eid_power_constraint(hapd, tailpos); - tailpos = hostapd_eid_channel_switch(hapd, tailpos); - tailpos = hostapd_eid_tpc_report(hapd, tailpos); - - /* ERP Information element */ - tailpos = hostapd_eid_erp_info(hapd, tailpos); - - /* Extended supported rates */ - tailpos = hostapd_eid_ext_supp_rates(hapd, tailpos); - - tailpos = hostapd_eid_wpa(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE - - tailpos, NULL); - - /* Wi-Fi Wireless Multimedia Extensions */ - if (hapd->conf->wme_enabled) - tailpos = hostapd_eid_wme(hapd, tailpos); - - tail_len = tailpos > tail ? tailpos - tail : 0; - - if (hostapd_set_beacon(hapd->conf->iface, hapd, (u8 *) head, head_len, - tail, tail_len)) - printf("Failed to set beacon head/tail\n"); - - free(tail); - free(head); - - if (hostapd_set_cts_protect(hapd, cts_protection)) - printf("Failed to set CTS protect in kernel driver\n"); - - if (hapd->iface && 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)) - printf("Failed to set Short Slot Time option in kernel " - "driver\n"); - - if (hapd->iface && 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)) - printf("Could not set preamble for kernel driver\n"); -} - - -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/contrib/hostapd/beacon.h b/contrib/hostapd/beacon.h deleted file mode 100644 index 18e0da2e89f6..000000000000 --- a/contrib/hostapd/beacon.h +++ /dev/null @@ -1,24 +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 - -void handle_probe_req(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt, - size_t len); -void ieee802_11_set_beacon(struct hostapd_data *hapd); -void ieee802_11_set_beacons(struct hostapd_iface *iface); - -#endif /* BEACON_H */ diff --git a/contrib/hostapd/build_config.h b/contrib/hostapd/build_config.h deleted file mode 100644 index 58bcda825345..000000000000 --- a/contrib/hostapd/build_config.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * wpa_supplicant/hostapd - Build time configuration defines - * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 EAP_TLS_FUNCS -#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 _CRT_SECURE_NO_DEPRECATE -#endif /* CONFIG_WIN32_DEFAULTS */ - -#endif /* BUILD_CONFIG_H */ diff --git a/contrib/hostapd/common.c b/contrib/hostapd/common.c deleted file mode 100644 index f226c68631b8..000000000000 --- a/contrib/hostapd/common.c +++ /dev/null @@ -1,599 +0,0 @@ -/* - * wpa_supplicant/hostapd / common helper functions, etc. - * Copyright (c) 2002-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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_FILE -static FILE *out_file = NULL; -#endif /* CONFIG_DEBUG_FILE */ -int wpa_debug_level = MSG_INFO; -int wpa_debug_show_keys = 0; -int wpa_debug_timestamp = 0; - - -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; -} - - -static 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 - * @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; -} - - -/** - * 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; - - /* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */ - os_get_time(&now); - sec = host_to_be32(now.sec + 2208988800U); /* Epoch to 1900 */ - /* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */ - usec = now.usec; - usec = host_to_be32(4295 * usec - (usec >> 5) - (usec >> 9)); - os_memcpy(buf, (u8 *) &sec, 4); - os_memcpy(buf + 4, (u8 *) &usec, 4); -} - - - -#ifndef CONFIG_NO_STDOUT_DEBUG - -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); -} - - -/** - * 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, char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - if (level >= wpa_debug_level) { - 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 */ - } - 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); -} - - -int wpa_debug_open_file(const char *path) -{ -#ifdef CONFIG_DEBUG_FILE - if (!path) - return 0; - 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; -#endif /* CONFIG_DEBUG_FILE */ -} - -#endif /* CONFIG_NO_STDOUT_DEBUG */ - - -#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; -} - - -void wpa_msg(void *ctx, int level, char *fmt, ...) -{ - va_list ap; - char *buf; - const int buflen = 2048; - int len; - - buf = os_malloc(buflen); - if (buf == NULL) { - wpa_printf(MSG_ERROR, "wpa_msg: Failed to allocate message " - "buffer"); - return; - } - va_start(ap, fmt); - len = vsnprintf(buf, buflen, fmt, ap); - va_end(ap); - wpa_printf(level, "%s", buf); - if (wpa_msg_cb) - wpa_msg_cb(ctx, level, buf, len); - os_free(buf); -} -#endif /* CONFIG_NO_WPA_MSG */ - - -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(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; -} diff --git a/contrib/hostapd/common.h b/contrib/hostapd/common.h deleted file mode 100644 index eda328af345d..000000000000 --- a/contrib/hostapd/common.h +++ /dev/null @@ -1,492 +0,0 @@ -/* - * wpa_supplicant/hostapd / common helper functions, etc. - * Copyright (c) 2002-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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" - -#ifdef __linux__ -#include <endian.h> -#include <byteswap.h> -#endif /* __linux__ */ - -#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) -#include <sys/types.h> -#include <sys/endian.h> -#define __BYTE_ORDER _BYTE_ORDER -#define __LITTLE_ENDIAN _LITTLE_ENDIAN -#define __BIG_ENDIAN _BIG_ENDIAN -#define bswap_16 bswap16 -#define bswap_32 bswap32 -#define bswap_64 bswap64 -#endif /* defined(__FreeBSD__) || defined(__NetBSD__) || - * defined(__DragonFly__) */ - -#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 CONFIG_NATIVE_WINDOWS -#include <winsock.h> - -typedef int socklen_t; - -#ifndef MSG_DONTWAIT -#define MSG_DONTWAIT 0 /* not supported */ -#endif - -#endif /* CONFIG_NATIVE_WINDOWS */ - -#if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS) - -#ifdef _MSC_VER -#define inline __inline -#endif /* _MSC_VER */ - -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) - -#else /* __CYGWIN__ */ - -#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) (n) -#define host_to_le16(n) (n) -#define be_to_host16(n) bswap_16(n) -#define host_to_be16(n) bswap_16(n) -#define le_to_host32(n) (n) -#define be_to_host32(n) bswap_32(n) -#define host_to_be32(n) bswap_32(n) -#define le_to_host64(n) (n) -#define host_to_le64(n) (n) -#define be_to_host64(n) bswap_64(n) -#define host_to_be64(n) 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 - -#endif /* __CYGWIN__ */ - -/* Macros for handling unaligned 16-bit variables */ -#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); \ - (a)[1] = (u8) (((u32) (val)) >> 8); \ - (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); \ - (a)[1] = (u8) (((u32) (val)) >> 16); \ - (a)[2] = (u8) (((u32) (val)) >> 8); \ - (a)[3] = (u8) (((u32) (val)) & 0xff); \ - } while (0) - -#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) - - -#ifndef ETH_ALEN -#define ETH_ALEN 6 -#endif - -#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 */ - -#ifndef WPA_TYPES_DEFINED -#ifdef CONFIG_USE_INTTYPES_H -#include <inttypes.h> -#else -#include <stdint.h> -#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 hostapd_get_rand os_get_random -int hwaddr_aton(const char *txt, u8 *addr); -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); - - -#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 - - -/* Debugging function - conditional printf and hex dump. Driver wrappers can - * use these for debugging purposes. */ - -enum { MSG_MSGDUMP, MSG_DEBUG, MSG_INFO, MSG_WARNING, MSG_ERROR }; - -#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_key(l,t,b,le) 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) - -#else /* CONFIG_NO_STDOUT_DEBUG */ - -int wpa_debug_open_file(const char *path); -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, 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); - -/** - * 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); - -/** - * 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); - -#endif /* CONFIG_NO_STDOUT_DEBUG */ - - -#ifdef CONFIG_NO_WPA_MSG -#define wpa_msg(args...) do { } while (0) -#define wpa_msg_register_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, 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); -#endif /* CONFIG_NO_WPA_MSG */ - - -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 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 - - -#ifdef _MSC_VER -#undef vsnprintf -#define vsnprintf _vsnprintf -#undef close -#define close closesocket -#endif /* _MSC_VER */ - - -#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 */ - -#define wpa_zalloc(s) os_zalloc((s)) - -#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(u8 *ssid, size_t ssid_len); - -typedef u32 __be32; -typedef u64 __be64; - -#endif /* COMMON_H */ diff --git a/contrib/hostapd/config.c b/contrib/hostapd/config.c deleted file mode 100644 index d1b2ba3fa5e0..000000000000 --- a/contrib/hostapd/config.c +++ /dev/null @@ -1,1994 +0,0 @@ -/* - * hostapd / Configuration file - * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 <grp.h> -#endif /* CONFIG_NATIVE_WINDOWS */ - -#include "hostapd.h" -#include "driver.h" -#include "sha1.h" -#include "eap.h" -#include "radius_client.h" -#include "wpa_common.h" - - -#define MAX_STA_COUNT 2007 - - -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) { - printf("VLAN file '%s' not readable.\n", 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) { - printf("Invalid VLAN ID at line %d in '%s'\n", - 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' || strlen(pos) > IFNAMSIZ) { - printf("Invalid VLAN ifname at line %d in '%s'\n", - line, fname); - fclose(f); - return -1; - } - - vlan = malloc(sizeof(*vlan)); - if (vlan == NULL) { - printf("Out of memory while reading VLAN interfaces " - "from '%s'\n", fname); - fclose(f); - return -1; - } - - memset(vlan, 0, sizeof(*vlan)); - vlan->vlan_id = vlan_id; - strncpy(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; -} - - -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; - free(prev); - } - - bss->vlan = NULL; -} - - -/* 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 = strchr(value, '.'); - d = 0; - if (pos) { - pos++; - if (*pos >= '0' && *pos <= '9') - d = *pos - '0'; - } - - return i * 10 + d; -} - - -static 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 = HOSTAPD_AUTH_OPEN | HOSTAPD_AUTH_SHARED_KEY; - - 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->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; -} - - -static struct hostapd_config * hostapd_config_defaults(void) -{ - struct hostapd_config *conf; - struct hostapd_bss_config *bss; - int i; - const int aCWmin = 15, aCWmax = 1024; - const struct hostapd_wme_ac_params ac_bk = - { aCWmin, aCWmax, 7, 0, 0 }; /* background traffic */ - const struct hostapd_wme_ac_params ac_be = - { aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */ - const struct hostapd_wme_ac_params ac_vi = /* video traffic */ - { aCWmin >> 1, aCWmin, 2, 3000 / 32, 1 }; - const struct hostapd_wme_ac_params ac_vo = /* voice traffic */ - { aCWmin >> 2, aCWmin >> 1, 2, 1500 / 32, 1 }; - - conf = wpa_zalloc(sizeof(*conf)); - bss = wpa_zalloc(sizeof(*bss)); - if (conf == NULL || bss == NULL) { - printf("Failed to allocate memory for configuration data.\n"); - free(conf); - free(bss); - return NULL; - } - - /* set default driver based on configuration */ - conf->driver = driver_lookup("default"); - if (conf->driver == NULL) { - printf("No default driver registered!\n"); - free(conf); - free(bss); - return NULL; - } - - bss->radius = wpa_zalloc(sizeof(*bss->radius)); - if (bss->radius == NULL) { - free(conf); - 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->bridge_packets = INTERNAL_BRIDGE_DO_NOT_CONTROL; - - memcpy(conf->country, "US ", 3); - - for (i = 0; i < NUM_TX_QUEUES; i++) - conf->tx_queue[i].aifs = -1; /* use hw default */ - - conf->wme_ac_params[0] = ac_be; - conf->wme_ac_params[1] = ac_bk; - conf->wme_ac_params[2] = ac_vi; - conf->wme_ac_params[3] = ac_vo; - - return conf; -} - - -static int hostapd_parse_ip_addr(const char *txt, struct hostapd_ip_addr *addr) -{ - 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 */ - - return -1; -} - - -int hostapd_mac_comp(const void *a, const void *b) -{ - return memcmp(a, b, sizeof(macaddr)); -} - - -int hostapd_mac_comp_empty(const void *a) -{ - macaddr empty = { 0 }; - return memcmp(a, empty, sizeof(macaddr)); -} - - -static int hostapd_config_read_maclist(const char *fname, macaddr **acl, - int *num) -{ - FILE *f; - char buf[128], *pos; - int line = 0; - u8 addr[ETH_ALEN]; - macaddr *newacl; - - if (!fname) - return 0; - - f = fopen(fname, "r"); - if (!f) { - printf("MAC list file '%s' not found.\n", 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)) { - printf("Invalid MAC address '%s' at line %d in '%s'\n", - buf, line, fname); - fclose(f); - return -1; - } - - newacl = (macaddr *) realloc(*acl, (*num + 1) * ETH_ALEN); - if (newacl == NULL) { - printf("MAC list reallocation failed\n"); - fclose(f); - return -1; - } - - *acl = newacl; - memcpy((*acl)[*num], addr, ETH_ALEN); - (*num)++; - } - - fclose(f); - - qsort(*acl, *num, sizeof(macaddr), hostapd_mac_comp); - - return 0; -} - - -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) { - printf("WPA PSK file '%s' not found.\n", 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)) { - printf("Invalid MAC address '%s' on line %d in '%s'\n", - buf, line, fname); - ret = -1; - break; - } - - psk = wpa_zalloc(sizeof(*psk)); - if (psk == NULL) { - printf("WPA PSK allocation failed\n"); - ret = -1; - break; - } - if (memcmp(addr, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0) - psk->group = 1; - else - memcpy(psk->addr, addr, ETH_ALEN); - - pos = buf + 17; - if (pos == '\0') { - printf("No PSK on line %d in '%s'\n", line, fname); - free(psk); - ret = -1; - break; - } - pos++; - - ok = 0; - len = 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) { - printf("Invalid PSK '%s' on line %d in '%s'\n", - pos, line, fname); - free(psk); - ret = -1; - break; - } - - psk->next = ssid->wpa_psk; - ssid->wpa_psk = psk; - } - - fclose(f); - - return ret; -} - - -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) { - printf("Warning: both WPA PSK and passphrase set. " - "Using passphrase.\n"); - free(ssid->wpa_psk); - } - ssid->wpa_psk = wpa_zalloc(sizeof(struct hostapd_wpa_psk)); - if (ssid->wpa_psk == NULL) { - printf("Unable to alloc space for PSK\n"); - return -1; - } - wpa_hexdump_ascii(MSG_DEBUG, "SSID", - (u8 *) ssid->ssid, ssid->ssid_len); - wpa_hexdump_ascii(MSG_DEBUG, "PSK (ASCII passphrase)", - (u8 *) ssid->wpa_passphrase, - strlen(ssid->wpa_passphrase)); - pbkdf2_sha1(ssid->wpa_passphrase, - ssid->ssid, ssid->ssid_len, - 4096, ssid->wpa_psk->psk, PMK_LEN); - wpa_hexdump(MSG_DEBUG, "PSK (from passphrase)", - ssid->wpa_psk->psk, PMK_LEN); - ssid->wpa_psk->group = 1; - - memset(ssid->wpa_passphrase, 0, - strlen(ssid->wpa_passphrase)); - free(ssid->wpa_passphrase); - ssid->wpa_passphrase = NULL; - } - - if (ssid->wpa_psk_file) { - if (hostapd_config_read_wpa_psk(ssid->wpa_psk_file, - &conf->ssid)) - return -1; - free(ssid->wpa_psk_file); - ssid->wpa_psk_file = NULL; - } - - 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) { - printf("EAP user file '%s' not found.\n", 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] != '*') { - printf("Invalid EAP identity (no \" in start) on " - "line %d in '%s'\n", line, fname); - goto failed; - } - - user = wpa_zalloc(sizeof(*user)); - if (user == NULL) { - printf("EAP user allocation failed\n"); - 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') { - printf("Invalid EAP identity (no \" in end) on" - " line %d in '%s'\n", line, fname); - goto failed; - } - - user->identity = malloc(pos - start); - if (user->identity == NULL) { - printf("Failed to allocate memory for EAP " - "identity\n"); - goto failed; - } - 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') { - printf("No EAP method on line %d in '%s'\n", - 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 = strchr(start, ','); - if (pos3) { - *pos3++ = '\0'; - } - user->methods[num_methods].method = - eap_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) - { - printf("Unsupported EAP type '%s' on line %d " - "in '%s'\n", start, line, fname); - goto failed; - } - - num_methods++; - if (num_methods >= EAP_USER_MAX_METHODS) - break; - if (pos3 == NULL) - break; - start = pos3; - } - if (num_methods == 0) { - printf("No EAP types configured on line %d in '%s'\n", - line, fname); - goto failed; - } - - if (pos == NULL) - goto done; - - while (*pos == ' ' || *pos == '\t') - pos++; - if (*pos == '\0') - goto done; - - if (strncmp(pos, "[ver=0]", 7) == 0) { - user->force_version = 0; - goto done; - } - - if (strncmp(pos, "[ver=1]", 7) == 0) { - user->force_version = 1; - goto done; - } - - if (strncmp(pos, "[2]", 3) == 0) { - user->phase2 = 1; - goto done; - } - - if (*pos == '"') { - pos++; - start = pos; - while (*pos != '"' && *pos != '\0') - pos++; - if (*pos == '\0') { - printf("Invalid EAP password (no \" in end) " - "on line %d in '%s'\n", line, fname); - goto failed; - } - - user->password = malloc(pos - start); - if (user->password == NULL) { - printf("Failed to allocate memory for EAP " - "password\n"); - goto failed; - } - memcpy(user->password, start, pos - start); - user->password_len = pos - start; - - pos++; - } else if (strncmp(pos, "hash:", 5) == 0) { - pos += 5; - pos2 = pos; - while (*pos2 != '\0' && *pos2 != ' ' && - *pos2 != '\t' && *pos2 != '#') - pos2++; - if (pos2 - pos != 32) { - printf("Invalid password hash on line %d in " - "'%s'\n", line, fname); - goto failed; - } - user->password = malloc(16); - if (user->password == NULL) { - printf("Failed to allocate memory for EAP " - "password hash\n"); - goto failed; - } - if (hexstr2bin(pos, user->password, 16) < 0) { - printf("Invalid hash password on line %d in " - "'%s'\n", 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) { - printf("Invalid hex password on line %d in " - "'%s'\n", line, fname); - goto failed; - } - user->password = malloc((pos2 - pos) / 2); - if (user->password == NULL) { - printf("Failed to allocate memory for EAP " - "password\n"); - goto failed; - } - if (hexstr2bin(pos, user->password, - (pos2 - pos) / 2) < 0) { - printf("Invalid hex password on line %d in " - "'%s'\n", line, fname); - goto failed; - } - user->password_len = (pos2 - pos) / 2; - pos = pos2; - } - - while (*pos == ' ' || *pos == '\t') - pos++; - if (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) { - free(user->password); - free(user->identity); - free(user); - } - ret = -1; - break; - } - - fclose(f); - - return ret; -} -#endif /* EAP_SERVER */ - - -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 = realloc(*server, (*num_server + 1) * sizeof(*nserv)); - if (nserv == NULL) - return -1; - - *server = nserv; - nserv = &nserv[*num_server]; - (*num_server)++; - (*curr_serv) = nserv; - - memset(nserv, 0, sizeof(*nserv)); - nserv->port = def_port; - ret = hostapd_parse_ip_addr(val, &nserv->addr); - nserv->index = server_index++; - - return ret; -} - - -static int hostapd_config_parse_key_mgmt(int line, const char *value) -{ - int val = 0, last; - char *start, *end, *buf; - - buf = 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 (strcmp(start, "WPA-PSK") == 0) - val |= WPA_KEY_MGMT_PSK; - else if (strcmp(start, "WPA-EAP") == 0) - val |= WPA_KEY_MGMT_IEEE8021X; - else { - printf("Line %d: invalid key_mgmt '%s'\n", - line, start); - free(buf); - return -1; - } - - if (last) - break; - start = end + 1; - } - - free(buf); - if (val == 0) { - printf("Line %d: no key_mgmt values configured.\n", 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 = 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 (strcmp(start, "CCMP") == 0) - val |= WPA_CIPHER_CCMP; - else if (strcmp(start, "TKIP") == 0) - val |= WPA_CIPHER_TKIP; - else if (strcmp(start, "WEP104") == 0) - val |= WPA_CIPHER_WEP104; - else if (strcmp(start, "WEP40") == 0) - val |= WPA_CIPHER_WEP40; - else if (strcmp(start, "NONE") == 0) - val |= WPA_CIPHER_NONE; - else { - printf("Line %d: invalid cipher '%s'.", line, start); - free(buf); - return -1; - } - - if (last) - break; - start = end + 1; - } - free(buf); - - if (val == 0) { - printf("Line %d: no cipher values configured.", line); - return -1; - } - return val; -} - - -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) { - printf("Invalid IEEE 802.1X configuration (no EAP " - "authenticator configured).\n"); - 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) { - printf("WPA-PSK enabled, but PSK or passphrase is not " - "configured.\n"); - 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)) { - printf("Duplicate BSSID " MACSTR - " on interface '%s' and '%s'.\n", - MAC2STR(bss->bssid), - conf->bss[i].iface, bss->iface); - return -1; - } - } - } - - return 0; -} - - -static int hostapd_config_check(struct hostapd_config *conf) -{ - size_t i; - - for (i = 0; i < conf->num_bss; i++) { - if (hostapd_config_check_bss(&conf->bss[i], conf)) - return -1; - } - - return 0; -} - - -static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx, - char *val) -{ - size_t len = 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] = malloc(len); - if (wep->key[keyidx] == NULL) - return -1; - memcpy(wep->key[keyidx], val + 1, len); - wep->len[keyidx] = len; - } else { - if (len & 1) - return -1; - len /= 2; - wep->key[keyidx] = 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; - - free(*rate_list); - *rate_list = NULL; - - pos = val; - count = 0; - while (*pos != '\0') { - if (*pos == ' ') - count++; - pos++; - } - - list = malloc(sizeof(int) * (count + 2)); - if (list == NULL) - return -1; - pos = val; - count = 0; - while (*pos != '\0') { - end = 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 = realloc(conf->bss, (conf->num_bss + 1) * - sizeof(struct hostapd_bss_config)); - if (bss == NULL) { - printf("Failed to allocate memory for multi-BSS entry\n"); - return -1; - } - conf->bss = bss; - - bss = &(conf->bss[conf->num_bss]); - memset(bss, 0, sizeof(*bss)); - bss->radius = wpa_zalloc(sizeof(*bss->radius)); - if (bss->radius == NULL) { - printf("Failed to allocate memory for multi-BSS RADIUS " - "data\n"); - return -1; - } - - conf->num_bss++; - conf->last_bss = bss; - - hostapd_config_defaults_bss(bss); - snprintf(bss->iface, sizeof(bss->iface), "%s", ifname); - memcpy(bss->ssid.vlan, bss->iface, IFNAMSIZ + 1); - - return 0; -} - - -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 */ - IEEE80211_TX_QUEUE_DATA4 = 4, - IEEE80211_TX_QUEUE_AFTER_BEACON = 6, - IEEE80211_TX_QUEUE_BEACON = 7 -}; - -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 (strncmp(pos, "data", 4) == 0 && - pos[4] >= '0' && pos[4] <= '9' && pos[5] == '_') { - num = pos[4] - '0'; - pos += 6; - } else if (strncmp(pos, "after_beacon_", 13) == 0) { - num = IEEE80211_TX_QUEUE_AFTER_BEACON; - pos += 13; - } else if (strncmp(pos, "beacon_", 7) == 0) { - num = IEEE80211_TX_QUEUE_BEACON; - pos += 7; - } else { - printf("Unknown tx_queue name '%s'\n", pos); - return -1; - } - - queue = &conf->tx_queue[num]; - - if (strcmp(pos, "aifs") == 0) { - queue->aifs = atoi(val); - if (queue->aifs < 0 || queue->aifs > 255) { - printf("Invalid AIFS value %d\n", queue->aifs); - return -1; - } - } else if (strcmp(pos, "cwmin") == 0) { - queue->cwmin = atoi(val); - if (!valid_cw(queue->cwmin)) { - printf("Invalid cwMin value %d\n", queue->cwmin); - return -1; - } - } else if (strcmp(pos, "cwmax") == 0) { - queue->cwmax = atoi(val); - if (!valid_cw(queue->cwmax)) { - printf("Invalid cwMax value %d\n", queue->cwmax); - return -1; - } - } else if (strcmp(pos, "burst") == 0) { - queue->burst = hostapd_config_read_int10(val); - } else { - printf("Unknown tx_queue field '%s'\n", pos); - return -1; - } - - queue->configured = 1; - - return 0; -} - - -static int hostapd_config_wme_ac(struct hostapd_config *conf, char *name, - char *val) -{ - int num, v; - char *pos; - struct hostapd_wme_ac_params *ac; - - /* skip 'wme_ac_' prefix */ - pos = name + 7; - if (strncmp(pos, "be_", 3) == 0) { - num = 0; - pos += 3; - } else if (strncmp(pos, "bk_", 3) == 0) { - num = 1; - pos += 3; - } else if (strncmp(pos, "vi_", 3) == 0) { - num = 2; - pos += 3; - } else if (strncmp(pos, "vo_", 3) == 0) { - num = 3; - pos += 3; - } else { - printf("Unknown wme name '%s'\n", pos); - return -1; - } - - ac = &conf->wme_ac_params[num]; - - if (strcmp(pos, "aifs") == 0) { - v = atoi(val); - if (v < 1 || v > 255) { - printf("Invalid AIFS value %d\n", v); - return -1; - } - ac->aifs = v; - } else if (strcmp(pos, "cwmin") == 0) { - v = atoi(val); - if (v < 0 || v > 12) { - printf("Invalid cwMin value %d\n", v); - return -1; - } - ac->cwmin = v; - } else if (strcmp(pos, "cwmax") == 0) { - v = atoi(val); - if (v < 0 || v > 12) { - printf("Invalid cwMax value %d\n", v); - return -1; - } - ac->cwmax = v; - } else if (strcmp(pos, "txop_limit") == 0) { - v = atoi(val); - if (v < 0 || v > 0xffff) { - printf("Invalid txop value %d\n", v); - return -1; - } - ac->txopLimit = v; - } else if (strcmp(pos, "acm") == 0) { - v = atoi(val); - if (v < 0 || v > 1) { - printf("Invalid acm value %d\n", v); - return -1; - } - ac->admission_control_mandatory = v; - } else { - printf("Unknown wme_ac_ field '%s'\n", pos); - return -1; - } - - return 0; -} - - -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; - size_t i; - - f = fopen(fname, "r"); - if (f == NULL) { - printf("Could not open configuration file '%s' for reading.\n", - fname); - return NULL; - } - - conf = hostapd_config_defaults(); - if (conf == NULL) { - 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 = strchr(buf, '='); - if (pos == NULL) { - printf("Line %d: invalid line '%s'\n", line, buf); - errors++; - continue; - } - *pos = '\0'; - pos++; - - if (strcmp(buf, "interface") == 0) { - snprintf(conf->bss[0].iface, - sizeof(conf->bss[0].iface), "%s", pos); - } else if (strcmp(buf, "bridge") == 0) { - snprintf(bss->bridge, sizeof(bss->bridge), "%s", pos); - } else if (strcmp(buf, "driver") == 0) { - conf->driver = driver_lookup(pos); - if (conf->driver == NULL) { - printf("Line %d: invalid/unknown driver " - "'%s'\n", line, pos); - errors++; - } - } else if (strcmp(buf, "debug") == 0) { - bss->debug = atoi(pos); - } else if (strcmp(buf, "logger_syslog_level") == 0) { - bss->logger_syslog_level = atoi(pos); - } else if (strcmp(buf, "logger_stdout_level") == 0) { - bss->logger_stdout_level = atoi(pos); - } else if (strcmp(buf, "logger_syslog") == 0) { - bss->logger_syslog = atoi(pos); - } else if (strcmp(buf, "logger_stdout") == 0) { - bss->logger_stdout = atoi(pos); - } else if (strcmp(buf, "dump_file") == 0) { - bss->dump_log_name = strdup(pos); - } else if (strcmp(buf, "ssid") == 0) { - bss->ssid.ssid_len = strlen(pos); - if (bss->ssid.ssid_len > HOSTAPD_MAX_SSID_LEN || - bss->ssid.ssid_len < 1) { - printf("Line %d: invalid SSID '%s'\n", line, - pos); - errors++; - } else { - memcpy(bss->ssid.ssid, pos, - bss->ssid.ssid_len); - bss->ssid.ssid[bss->ssid.ssid_len] = '\0'; - bss->ssid.ssid_set = 1; - } - } else if (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) { - printf("Line %d: unknown macaddr_acl %d\n", - line, bss->macaddr_acl); - } - } else if (strcmp(buf, "accept_mac_file") == 0) { - if (hostapd_config_read_maclist(pos, &bss->accept_mac, - &bss->num_accept_mac)) - { - printf("Line %d: Failed to read " - "accept_mac_file '%s'\n", - line, pos); - errors++; - } - } else if (strcmp(buf, "deny_mac_file") == 0) { - if (hostapd_config_read_maclist(pos, &bss->deny_mac, - &bss->num_deny_mac)) - { - printf("Line %d: Failed to read " - "deny_mac_file '%s'\n", - line, pos); - errors++; - } - } else if (strcmp(buf, "ap_max_inactivity") == 0) { - bss->ap_max_inactivity = atoi(pos); - } else if (strcmp(buf, "country_code") == 0) { - memcpy(conf->country, pos, 2); - /* FIX: make this configurable */ - conf->country[2] = ' '; - } else if (strcmp(buf, "ieee80211d") == 0) { - conf->ieee80211d = atoi(pos); - } else if (strcmp(buf, "ieee80211h") == 0) { - conf->ieee80211h = atoi(pos); - } else if (strcmp(buf, "assoc_ap_addr") == 0) { - if (hwaddr_aton(pos, bss->assoc_ap_addr)) { - printf("Line %d: invalid MAC address '%s'\n", - line, pos); - errors++; - } - bss->assoc_ap = 1; - } else if (strcmp(buf, "ieee8021x") == 0) { - bss->ieee802_1x = atoi(pos); - } else if (strcmp(buf, "eapol_version") == 0) { - bss->eapol_version = atoi(pos); - if (bss->eapol_version < 1 || - bss->eapol_version > 2) { - printf("Line %d: invalid EAPOL " - "version (%d): '%s'.\n", - line, bss->eapol_version, pos); - errors++; - } else - wpa_printf(MSG_DEBUG, "eapol_version=%d", - bss->eapol_version); -#ifdef EAP_SERVER - } else if (strcmp(buf, "eap_authenticator") == 0) { - bss->eap_server = atoi(pos); - printf("Line %d: obsolete eap_authenticator used; " - "this has been renamed to eap_server\n", line); - } else if (strcmp(buf, "eap_server") == 0) { - bss->eap_server = atoi(pos); - } else if (strcmp(buf, "eap_user_file") == 0) { - if (hostapd_config_read_eap_user(pos, bss)) - errors++; - } else if (strcmp(buf, "ca_cert") == 0) { - free(bss->ca_cert); - bss->ca_cert = strdup(pos); - } else if (strcmp(buf, "server_cert") == 0) { - free(bss->server_cert); - bss->server_cert = strdup(pos); - } else if (strcmp(buf, "private_key") == 0) { - free(bss->private_key); - bss->private_key = strdup(pos); - } else if (strcmp(buf, "private_key_passwd") == 0) { - free(bss->private_key_passwd); - bss->private_key_passwd = strdup(pos); - } else if (strcmp(buf, "check_crl") == 0) { - bss->check_crl = atoi(pos); -#ifdef EAP_SIM - } else if (strcmp(buf, "eap_sim_db") == 0) { - free(bss->eap_sim_db); - bss->eap_sim_db = strdup(pos); -#endif /* EAP_SIM */ -#endif /* EAP_SERVER */ - } else if (strcmp(buf, "eap_message") == 0) { - char *term; - bss->eap_req_id_text = strdup(pos); - if (bss->eap_req_id_text == NULL) { - printf("Line %d: Failed to allocate memory " - "for eap_req_id_text\n", line); - errors++; - continue; - } - bss->eap_req_id_text_len = - strlen(bss->eap_req_id_text); - term = strstr(bss->eap_req_id_text, "\\0"); - if (term) { - *term++ = '\0'; - 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 (strcmp(buf, "wep_key_len_broadcast") == 0) { - bss->default_wep_key_len = atoi(pos); - if (bss->default_wep_key_len > 13) { - printf("Line %d: invalid WEP key len %lu " - "(= %lu bits)\n", line, - (unsigned long) - bss->default_wep_key_len, - (unsigned long) - bss->default_wep_key_len * 8); - errors++; - } - } else if (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) { - printf("Line %d: invalid WEP key len %d " - "(= %d bits)\n", line, - bss->individual_wep_key_len, - bss->individual_wep_key_len * 8); - errors++; - } - } else if (strcmp(buf, "wep_rekey_period") == 0) { - bss->wep_rekeying_period = atoi(pos); - if (bss->wep_rekeying_period < 0) { - printf("Line %d: invalid period %d\n", - line, bss->wep_rekeying_period); - errors++; - } - } else if (strcmp(buf, "eap_reauth_period") == 0) { - bss->eap_reauth_period = atoi(pos); - if (bss->eap_reauth_period < 0) { - printf("Line %d: invalid period %d\n", - line, bss->eap_reauth_period); - errors++; - } - } else if (strcmp(buf, "eapol_key_index_workaround") == 0) { - bss->eapol_key_index_workaround = atoi(pos); -#ifdef CONFIG_IAPP - } else if (strcmp(buf, "iapp_interface") == 0) { - bss->ieee802_11f = 1; - snprintf(bss->iapp_iface, sizeof(bss->iapp_iface), - "%s", pos); -#endif /* CONFIG_IAPP */ - } else if (strcmp(buf, "own_ip_addr") == 0) { - if (hostapd_parse_ip_addr(pos, &bss->own_ip_addr)) { - printf("Line %d: invalid IP address '%s'\n", - line, pos); - errors++; - } - } else if (strcmp(buf, "nas_identifier") == 0) { - bss->nas_identifier = strdup(pos); - } else if (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)) { - printf("Line %d: invalid IP address '%s'\n", - line, pos); - errors++; - } - } else if (bss->radius->auth_server && - strcmp(buf, "auth_server_port") == 0) { - bss->radius->auth_server->port = atoi(pos); - } else if (bss->radius->auth_server && - strcmp(buf, "auth_server_shared_secret") == 0) { - int len = strlen(pos); - if (len == 0) { - /* RFC 2865, Ch. 3 */ - printf("Line %d: empty shared secret is not " - "allowed.\n", line); - errors++; - } - bss->radius->auth_server->shared_secret = - (u8 *) strdup(pos); - bss->radius->auth_server->shared_secret_len = len; - } else if (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)) { - printf("Line %d: invalid IP address '%s'\n", - line, pos); - errors++; - } - } else if (bss->radius->acct_server && - strcmp(buf, "acct_server_port") == 0) { - bss->radius->acct_server->port = atoi(pos); - } else if (bss->radius->acct_server && - strcmp(buf, "acct_server_shared_secret") == 0) { - int len = strlen(pos); - if (len == 0) { - /* RFC 2865, Ch. 3 */ - printf("Line %d: empty shared secret is not " - "allowed.\n", line); - errors++; - } - bss->radius->acct_server->shared_secret = - (u8 *) strdup(pos); - bss->radius->acct_server->shared_secret_len = len; - } else if (strcmp(buf, "radius_retry_primary_interval") == 0) { - bss->radius->retry_primary_interval = atoi(pos); - } else if (strcmp(buf, "radius_acct_interim_interval") == 0) { - bss->radius->acct_interim_interval = atoi(pos); - } else if (strcmp(buf, "auth_algs") == 0) { - bss->auth_algs = atoi(pos); - if (bss->auth_algs == 0) { - printf("Line %d: no authentication algorithms " - "allowed\n", - line); - errors++; - } - } else if (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) { - printf("Line %d: Invalid max_num_sta=%d; " - "allowed range 0..%d\n", line, - bss->max_num_sta, MAX_STA_COUNT); - errors++; - } - } else if (strcmp(buf, "wpa") == 0) { - bss->wpa = atoi(pos); - } else if (strcmp(buf, "wpa_group_rekey") == 0) { - bss->wpa_group_rekey = atoi(pos); - } else if (strcmp(buf, "wpa_strict_rekey") == 0) { - bss->wpa_strict_rekey = atoi(pos); - } else if (strcmp(buf, "wpa_gmk_rekey") == 0) { - bss->wpa_gmk_rekey = atoi(pos); - } else if (strcmp(buf, "wpa_passphrase") == 0) { - int len = strlen(pos); - if (len < 8 || len > 63) { - printf("Line %d: invalid WPA passphrase length" - " %d (expected 8..63)\n", line, len); - errors++; - } else { - free(bss->ssid.wpa_passphrase); - bss->ssid.wpa_passphrase = strdup(pos); - } - } else if (strcmp(buf, "wpa_psk") == 0) { - free(bss->ssid.wpa_psk); - bss->ssid.wpa_psk = - wpa_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') { - printf("Line %d: Invalid PSK '%s'.\n", line, - pos); - errors++; - } else { - bss->ssid.wpa_psk->group = 1; - } - } else if (strcmp(buf, "wpa_psk_file") == 0) { - free(bss->ssid.wpa_psk_file); - bss->ssid.wpa_psk_file = strdup(pos); - if (!bss->ssid.wpa_psk_file) { - printf("Line %d: allocation failed\n", line); - errors++; - } - } else if (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 (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)) { - printf("Line %d: unsupported pairwise " - "cipher suite '%s'\n", - bss->wpa_pairwise, pos); - errors++; - } else { - if (bss->wpa_pairwise & WPA_CIPHER_TKIP) - bss->wpa_group = WPA_CIPHER_TKIP; - else - bss->wpa_group = WPA_CIPHER_CCMP; - } -#ifdef CONFIG_RSN_PREAUTH - } else if (strcmp(buf, "rsn_preauth") == 0) { - bss->rsn_preauth = atoi(pos); - } else if (strcmp(buf, "rsn_preauth_interfaces") == 0) { - bss->rsn_preauth_interfaces = strdup(pos); -#endif /* CONFIG_RSN_PREAUTH */ -#ifdef CONFIG_PEERKEY - } else if (strcmp(buf, "peerkey") == 0) { - bss->peerkey = atoi(pos); -#endif /* CONFIG_PEERKEY */ - } else if (strcmp(buf, "ctrl_interface") == 0) { - free(bss->ctrl_interface); - bss->ctrl_interface = strdup(pos); - } else if (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 */ -#ifdef RADIUS_SERVER - } else if (strcmp(buf, "radius_server_clients") == 0) { - free(bss->radius_server_clients); - bss->radius_server_clients = strdup(pos); - } else if (strcmp(buf, "radius_server_auth_port") == 0) { - bss->radius_server_auth_port = atoi(pos); - } else if (strcmp(buf, "radius_server_ipv6") == 0) { - bss->radius_server_ipv6 = atoi(pos); -#endif /* RADIUS_SERVER */ - } else if (strcmp(buf, "test_socket") == 0) { - free(bss->test_socket); - bss->test_socket = strdup(pos); - } else if (strcmp(buf, "use_pae_group_addr") == 0) { - bss->use_pae_group_addr = atoi(pos); - } else if (strcmp(buf, "hw_mode") == 0) { - if (strcmp(pos, "a") == 0) - conf->hw_mode = HOSTAPD_MODE_IEEE80211A; - else if (strcmp(pos, "b") == 0) - conf->hw_mode = HOSTAPD_MODE_IEEE80211B; - else if (strcmp(pos, "g") == 0) - conf->hw_mode = HOSTAPD_MODE_IEEE80211G; - else { - printf("Line %d: unknown hw_mode '%s'\n", - line, pos); - errors++; - } - } else if (strcmp(buf, "channel") == 0) { - conf->channel = atoi(pos); - } else if (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) { - printf("Line %d: invalid beacon_int %d " - "(expected 15..65535)\n", - line, val); - errors++; - } else - conf->beacon_int = val; - } else if (strcmp(buf, "dtim_period") == 0) { - bss->dtim_period = atoi(pos); - if (bss->dtim_period < 1 || bss->dtim_period > 255) { - printf("Line %d: invalid dtim_period %d\n", - line, bss->dtim_period); - errors++; - } - } else if (strcmp(buf, "rts_threshold") == 0) { - conf->rts_threshold = atoi(pos); - if (conf->rts_threshold < 0 || - conf->rts_threshold > 2347) { - printf("Line %d: invalid rts_threshold %d\n", - line, conf->rts_threshold); - errors++; - } - } else if (strcmp(buf, "fragm_threshold") == 0) { - conf->fragm_threshold = atoi(pos); - if (conf->fragm_threshold < 256 || - conf->fragm_threshold > 2346) { - printf("Line %d: invalid fragm_threshold %d\n", - line, conf->fragm_threshold); - errors++; - } - } else if (strcmp(buf, "send_probe_response") == 0) { - int val = atoi(pos); - if (val != 0 && val != 1) { - printf("Line %d: invalid send_probe_response " - "%d (expected 0 or 1)\n", line, val); - } else - conf->send_probe_response = val; - } else if (strcmp(buf, "supported_rates") == 0) { - if (hostapd_parse_rates(&conf->supported_rates, pos)) { - printf("Line %d: invalid rate list\n", line); - errors++; - } - } else if (strcmp(buf, "basic_rates") == 0) { - if (hostapd_parse_rates(&conf->basic_rates, pos)) { - printf("Line %d: invalid rate list\n", line); - errors++; - } - } else if (strcmp(buf, "ignore_broadcast_ssid") == 0) { - bss->ignore_broadcast_ssid = atoi(pos); - } else if (strcmp(buf, "bridge_packets") == 0) { - conf->bridge_packets = atoi(pos); - } else if (strcmp(buf, "wep_default_key") == 0) { - bss->ssid.wep.idx = atoi(pos); - if (bss->ssid.wep.idx > 3) { - printf("Invalid wep_default_key index %d\n", - bss->ssid.wep.idx); - errors++; - } - } else if (strcmp(buf, "wep_key0") == 0 || - strcmp(buf, "wep_key1") == 0 || - strcmp(buf, "wep_key2") == 0 || - strcmp(buf, "wep_key3") == 0) { - if (hostapd_config_read_wep(&bss->ssid.wep, - buf[7] - '0', pos)) { - printf("Line %d: invalid WEP key '%s'\n", - line, buf); - errors++; - } - } else if (strcmp(buf, "dynamic_vlan") == 0) { - bss->ssid.dynamic_vlan = atoi(pos); - } else if (strcmp(buf, "vlan_file") == 0) { - if (hostapd_config_read_vlan_file(bss, pos)) { - printf("Line %d: failed to read VLAN file " - "'%s'\n", line, pos); - errors++; - } -#ifdef CONFIG_FULL_DYNAMIC_VLAN - } else if (strcmp(buf, "vlan_tagged_interface") == 0) { - bss->ssid.vlan_tagged_interface = strdup(pos); -#endif /* CONFIG_FULL_DYNAMIC_VLAN */ - } else if (strcmp(buf, "passive_scan_interval") == 0) { - conf->passive_scan_interval = atoi(pos); - } else if (strcmp(buf, "passive_scan_listen") == 0) { - conf->passive_scan_listen = atoi(pos); - } else if (strcmp(buf, "passive_scan_mode") == 0) { - conf->passive_scan_mode = atoi(pos); - } else if (strcmp(buf, "ap_table_max_size") == 0) { - conf->ap_table_max_size = atoi(pos); - } else if (strcmp(buf, "ap_table_expiration_time") == 0) { - conf->ap_table_expiration_time = atoi(pos); - } else if (strncmp(buf, "tx_queue_", 9) == 0) { - if (hostapd_config_tx_queue(conf, buf, pos)) { - printf("Line %d: invalid TX queue item\n", - line); - errors++; - } - } else if (strcmp(buf, "wme_enabled") == 0) { - bss->wme_enabled = atoi(pos); - } else if (strncmp(buf, "wme_ac_", 7) == 0) { - if (hostapd_config_wme_ac(conf, buf, pos)) { - printf("Line %d: invalid wme ac item\n", - line); - errors++; - } - } else if (strcmp(buf, "bss") == 0) { - if (hostapd_config_bss(conf, pos)) { - printf("Line %d: invalid bss item\n", line); - errors++; - } - } else if (strcmp(buf, "bssid") == 0) { - if (bss == conf->bss) { - printf("Line %d: bssid item not allowed " - "for the default interface\n", line); - errors++; - } else if (hwaddr_aton(pos, bss->bssid)) { - printf("Line %d: invalid bssid item\n", line); - errors++; - } -#ifdef CONFIG_IEEE80211W - } else if (strcmp(buf, "ieee80211w") == 0) { - bss->ieee80211w = atoi(pos); -#endif /* CONFIG_IEEE80211W */ - } else { - printf("Line %d: unknown configuration item '%s'\n", - line, buf); - errors++; - } - } - - fclose(f); - - 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; - } - - for (i = 0; i < conf->num_bss; i++) { - bss = &conf->bss[i]; - - 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++; - - if (errors) { - printf("%d errors found in configuration file '%s'\n", - errors, fname); - hostapd_config_free(conf); - conf = NULL; - } - - return conf; -} - - -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] || - 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++) { - free(servers[i].shared_secret); - } - free(servers); -} - - -static void hostapd_config_free_eap_user(struct hostapd_eap_user *user) -{ - free(user->identity); - free(user->password); - free(user); -} - - -static void hostapd_config_free_wep(struct hostapd_wep_keys *keys) -{ - int i; - for (i = 0; i < NUM_WEP_KEYS; i++) { - 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; - free(prev); - } - - free(conf->ssid.wpa_passphrase); - free(conf->ssid.wpa_psk_file); -#ifdef CONFIG_FULL_DYNAMIC_VLAN - 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); - } - - free(conf->dump_log_name); - free(conf->eap_req_id_text); - free(conf->accept_mac); - free(conf->deny_mac); - 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); - free(conf->rsn_preauth_interfaces); - free(conf->ctrl_interface); - free(conf->ca_cert); - free(conf->server_cert); - free(conf->private_key); - free(conf->private_key_passwd); - free(conf->eap_sim_db); - free(conf->radius_server_clients); - free(conf->test_socket); - 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]); - free(ssid->dyn_vlan_keys[i]); - } - free(ssid->dyn_vlan_keys); - ssid->dyn_vlan_keys = NULL; - } -} - - -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]); - free(conf->bss); - - free(conf); -} - - -/* Perform a binary search for given MAC address from a pre-sorted list. - * Returns 1 if address is in the list or 0 if not. */ -int hostapd_maclist_found(macaddr *list, int num_entries, const u8 *addr) -{ - int start, end, middle, res; - - start = 0; - end = num_entries - 1; - - while (start <= end) { - middle = (start + end) / 2; - res = memcmp(list[middle], addr, ETH_ALEN); - if (res == 0) - 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 || 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; - - while (user) { - if (!phase2 && user->identity == NULL) { - /* Wildcard match */ - break; - } - - if (!phase2 && user->wildcard_prefix && - identity_len >= user->identity_len && - memcmp(user->identity, identity, user->identity_len) == 0) - { - /* Wildcard prefix match */ - break; - } - - if (user->phase2 == !!phase2 && - user->identity_len == identity_len && - memcmp(user->identity, identity, identity_len) == 0) - break; - user = user->next; - } - - return user; -} diff --git a/contrib/hostapd/config.h b/contrib/hostapd/config.h deleted file mode 100644 index fafe8e041106..000000000000 --- a/contrib/hostapd/config.h +++ /dev/null @@ -1,362 +0,0 @@ -/* - * hostapd / Configuration file - * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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_H -#define CONFIG_H - -#include "config_types.h" - -typedef u8 macaddr[ETH_ALEN]; - -struct hostapd_radius_servers; - -#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() */ -}; - - -#define NUM_TX_QUEUES 8 - -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 */ - int configured; -}; - -struct hostapd_wme_ac_params { - int cwmin; - int cwmax; - int aifs; - int txopLimit; /* 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]; - - enum { - HOSTAPD_LEVEL_DEBUG_VERBOSE = 0, - HOSTAPD_LEVEL_DEBUG = 1, - HOSTAPD_LEVEL_INFO = 2, - HOSTAPD_LEVEL_NOTICE = 3, - HOSTAPD_LEVEL_WARNING = 4 - } logger_syslog_level, logger_stdout_level; - -#define HOSTAPD_MODULE_IEEE80211 BIT(0) -#define HOSTAPD_MODULE_IEEE8021X BIT(1) -#define HOSTAPD_MODULE_RADIUS BIT(2) -#define HOSTAPD_MODULE_WPA BIT(3) -#define HOSTAPD_MODULE_DRIVER BIT(4) -#define HOSTAPD_MODULE_IAPP BIT(5) -#define HOSTAPD_MODULE_MLME BIT(6) - unsigned int logger_syslog; /* module bitfield */ - unsigned int logger_stdout; /* module bitfield */ - - enum { HOSTAPD_DEBUG_NO = 0, HOSTAPD_DEBUG_MINIMAL = 1, - HOSTAPD_DEBUG_VERBOSE = 2, - HOSTAPD_DEBUG_MSGDUMPS = 3, - HOSTAPD_DEBUG_EXCESSIVE = 4 } debug; /* debug verbosity level */ - 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; - - 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 */ - - u8 assoc_ap_addr[ETH_ALEN]; - int assoc_ap; /* whether assoc_ap_addr is set */ - - enum { - ACCEPT_UNLESS_DENIED = 0, - DENY_UNLESS_ACCEPTED = 1, - USE_EXTERNAL_RADIUS_AUTH = 2 - } macaddr_acl; - macaddr *accept_mac; - int num_accept_mac; - macaddr *deny_mac; - int num_deny_mac; - -#define HOSTAPD_AUTH_OPEN BIT(0) -#define HOSTAPD_AUTH_SHARED_KEY BIT(1) - int auth_algs; /* bitfield of allowed IEEE 802.11 authentication - * algorithms */ - -#define HOSTAPD_WPA_VERSION_WPA BIT(0) -#define HOSTAPD_WPA_VERSION_WPA2 BIT(1) - int wpa; -#define WPA_KEY_MGMT_IEEE8021X BIT(0) -#define WPA_KEY_MGMT_PSK BIT(1) - int wpa_key_mgmt; -#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) - enum { - NO_IEEE80211W = 0, - IEEE80211W_OPTIONAL = 1, - IEEE80211W_REQUIRED = 2 - } ieee80211w; -#endif /* CONFIG_IEEE80211W */ - int wpa_pairwise; - int wpa_group; - int wpa_group_rekey; - int wpa_strict_rekey; - int wpa_gmk_rekey; - int rsn_preauth; - char *rsn_preauth_interfaces; - int peerkey; - - char *ctrl_interface; /* directory for UNIX domain sockets */ - gid_t ctrl_interface_gid; - int ctrl_interface_gid_set; - - char *ca_cert; - char *server_cert; - char *private_key; - char *private_key_passwd; - int check_crl; - - 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 wme_enabled; - - struct hostapd_vlan *vlan, *vlan_tail; - - macaddr bssid; -}; - - -typedef enum { - HOSTAPD_MODE_IEEE80211B, - HOSTAPD_MODE_IEEE80211G, - HOSTAPD_MODE_IEEE80211A, - NUM_HOSTAPD_MODES -} hostapd_hw_mode; - - -/** - * struct hostapd_config - Per-radio interface configuration - */ -struct hostapd_config { - struct hostapd_bss_config *bss, *last_bss; - struct hostapd_radius_servers *radius; - size_t num_bss; - - u16 beacon_int; - int rts_threshold; - int fragm_threshold; - u8 send_probe_response; - u8 channel; - 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 driver_ops *driver; - - int passive_scan_interval; /* seconds, 0 = disabled */ - int passive_scan_listen; /* usec */ - int passive_scan_mode; - 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; - unsigned int ieee80211h; /* Enable/Disable 80211h */ - - struct hostapd_tx_queue_params tx_queue[NUM_TX_QUEUES]; - - /* - * WME 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_wme_ac_params wme_ac_params[4]; - - enum { - INTERNAL_BRIDGE_DO_NOT_CONTROL = -1, - INTERNAL_BRIDGE_DISABLED = 0, - INTERNAL_BRIDGE_ENABLED = 1 - } bridge_packets; -}; - - -int hostapd_mac_comp(const void *a, const void *b); -int hostapd_mac_comp_empty(const void *a); -struct hostapd_config * hostapd_config_read(const char *fname); -void hostapd_config_free(struct hostapd_config *conf); -int hostapd_maclist_found(macaddr *list, int num_entries, const u8 *addr); -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 /* CONFIG_H */ diff --git a/contrib/hostapd/config_types.h b/contrib/hostapd/config_types.h deleted file mode 100644 index ffcffa3c0cd4..000000000000 --- a/contrib/hostapd/config_types.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * hostapd / Shared configuration file defines - * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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_TYPES_H -#define CONFIG_TYPES_H - -struct hostapd_ip_addr { - union { - struct in_addr v4; -#ifdef CONFIG_IPV6 - struct in6_addr v6; -#endif /* CONFIG_IPV6 */ - } u; - int af; /* AF_INET / AF_INET6 */ -}; - -#endif /* CONFIG_TYPES_H */ diff --git a/contrib/hostapd/crypto.c b/contrib/hostapd/crypto.c deleted file mode 100644 index c5edd24c4b55..000000000000 --- a/contrib/hostapd/crypto.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - * WPA Supplicant / wrapper functions for libcrypto - * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 <openssl/opensslv.h> -#include <openssl/md4.h> -#include <openssl/md5.h> -#include <openssl/sha.h> -#include <openssl/des.h> -#include <openssl/aes.h> - -#include "common.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 */ - - -void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - MD4_CTX ctx; - size_t i; - - MD4_Init(&ctx); - for (i = 0; i < num_elem; i++) - MD4_Update(&ctx, addr[i], len[i]); - MD4_Final(mac, &ctx); -} - - -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); -} - - -#ifdef EAP_TLS_FUNCS -void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - MD5_CTX ctx; - size_t i; - - MD5_Init(&ctx); - for (i = 0; i < num_elem; i++) - MD5_Update(&ctx, addr[i], len[i]); - MD5_Final(mac, &ctx); -} - - -void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - SHA_CTX ctx; - size_t i; - - SHA1_Init(&ctx); - for (i = 0; i < num_elem; i++) - SHA1_Update(&ctx, addr[i], len[i]); - SHA1_Final(mac, &ctx); -} - - -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; -} - - -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); -} -#endif /* EAP_TLS_FUNCS */ diff --git a/contrib/hostapd/crypto.h b/contrib/hostapd/crypto.h deleted file mode 100644 index 00b13b91c48e..000000000000 --- a/contrib/hostapd/crypto.h +++ /dev/null @@ -1,413 +0,0 @@ -/* - * WPA Supplicant / wrapper functions for crypto libraries - * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 - */ -void 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 - */ -void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); - -/** - * 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 - */ -void 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 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 - */ -void 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 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 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 - * 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); - -/** - * 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 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_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 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 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 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 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); - -#endif /* CRYPTO_H */ diff --git a/contrib/hostapd/ctrl_iface.c b/contrib/hostapd/ctrl_iface.c deleted file mode 100644 index 9863782ed148..000000000000 --- a/contrib/hostapd/ctrl_iface.c +++ /dev/null @@ -1,499 +0,0 @@ -/* - * hostapd / UNIX domain socket -based control interface - * Copyright (c) 2004, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 <sys/un.h> -#include <sys/stat.h> - -#include "hostapd.h" -#include "eloop.h" -#include "config.h" -#include "eapol_sm.h" -#include "ieee802_1x.h" -#include "wpa.h" -#include "radius_client.h" -#include "ieee802_11.h" -#include "ctrl_iface.h" -#include "sta_info.h" -#include "accounting.h" - - -struct wpa_ctrl_dst { - struct wpa_ctrl_dst *next; - struct sockaddr_un addr; - socklen_t addrlen; - int debug_level; - int errors; -}; - - -static int hostapd_ctrl_iface_attach(struct hostapd_data *hapd, - struct sockaddr_un *from, - socklen_t fromlen) -{ - struct wpa_ctrl_dst *dst; - - dst = wpa_zalloc(sizeof(*dst)); - if (dst == NULL) - return -1; - 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); - 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 && - memcmp(from->sun_path, dst->addr.sun_path, fromlen) == 0) { - if (prev == NULL) - hapd->ctrl_dst = dst->next; - else - prev->next = dst->next; - free(dst); - wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached", - (u8 *) from->sun_path, fromlen); - 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 && - memcmp(from->sun_path, dst->addr.sun_path, fromlen) == 0) { - wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor " - "level", (u8 *) from->sun_path, fromlen); - dst->debug_level = atoi(level); - return 0; - } - dst = dst->next; - } - - return -1; -} - - -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 = snprintf(buf, buflen, "FAIL\n"); - if (ret < 0 || (size_t) ret >= buflen) - return 0; - return ret; - } - - len = 0; - ret = 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; - - return len; -} - - -static 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); -} - - -static 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 = 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); -} - - -static 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 = 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); -} - - -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); - accounting_sta_get_id(hapd, sta); - return 0; -} - - -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; - - res = recvfrom(sock, buf, sizeof(buf) - 1, 0, - (struct sockaddr *) &from, &fromlen); - if (res < 0) { - perror("recvfrom(ctrl_iface)"); - return; - } - buf[res] = '\0'; - wpa_hexdump_ascii(MSG_DEBUG, "RX ctrl_iface", (u8 *) buf, res); - - reply = malloc(reply_size); - if (reply == NULL) { - sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, - fromlen); - return; - } - - memcpy(reply, "OK\n", 3); - reply_len = 3; - - if (strcmp(buf, "PING") == 0) { - memcpy(reply, "PONG\n", 5); - reply_len = 5; - } else if (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; - } - 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; - } - } else if (strcmp(buf, "STA-FIRST") == 0) { - reply_len = hostapd_ctrl_iface_sta_first(hapd, reply, - reply_size); - } else if (strncmp(buf, "STA ", 4) == 0) { - reply_len = hostapd_ctrl_iface_sta(hapd, buf + 4, reply, - reply_size); - } else if (strncmp(buf, "STA-NEXT ", 9) == 0) { - reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply, - reply_size); - } else if (strcmp(buf, "ATTACH") == 0) { - if (hostapd_ctrl_iface_attach(hapd, &from, fromlen)) - reply_len = -1; - } else if (strcmp(buf, "DETACH") == 0) { - if (hostapd_ctrl_iface_detach(hapd, &from, fromlen)) - reply_len = -1; - } else if (strncmp(buf, "LEVEL ", 6) == 0) { - if (hostapd_ctrl_iface_level(hapd, &from, fromlen, - buf + 6)) - reply_len = -1; - } else if (strncmp(buf, "NEW_STA ", 8) == 0) { - if (hostapd_ctrl_iface_new_sta(hapd, buf + 8)) - reply_len = -1; - } else { - memcpy(reply, "UNKNOWN COMMAND\n", 16); - reply_len = 16; - } - - if (reply_len < 0) { - memcpy(reply, "FAIL\n", 5); - reply_len = 5; - } - sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen); - 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 = strlen(hapd->conf->ctrl_interface) + strlen(hapd->conf->iface) + - 2; - buf = malloc(len); - if (buf == NULL) - return NULL; - - snprintf(buf, len, "%s/%s", - hapd->conf->ctrl_interface, hapd->conf->iface); - buf[len - 1] = '\0'; - return buf; -} - - -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 (strlen(hapd->conf->ctrl_interface) + 1 + 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; - } - - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - fname = hostapd_ctrl_iface_path(hapd); - if (fname == NULL) - goto fail; - strncpy(addr.sun_path, fname, sizeof(addr.sun_path)); - if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror("bind(PF_UNIX)"); - 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; - } - free(fname); - - hapd->ctrl_sock = s; - eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd, - NULL); - - return 0; - -fail: - if (s >= 0) - close(s); - if (fname) { - unlink(fname); - 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); - 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; - free(prev); - } -} - - -void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level, - 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; - - snprintf(levelstr, sizeof(levelstr), "<%d>", level); - io[0].iov_base = levelstr; - io[0].iov_len = strlen(levelstr); - io[1].iov_base = buf; - io[1].iov_len = len; - 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); - msg.msg_name = &dst->addr; - msg.msg_namelen = dst->addrlen; - if (sendmsg(hapd->ctrl_sock, &msg, 0) < 0) { - fprintf(stderr, "CTRL_IFACE monitor[%d]: ", - idx); - perror("sendmsg"); - dst->errors++; - if (dst->errors > 10) { - hostapd_ctrl_iface_detach( - hapd, &dst->addr, - dst->addrlen); - } - } else - dst->errors = 0; - } - idx++; - dst = next; - } -} - -#endif /* CONFIG_NATIVE_WINDOWS */ diff --git a/contrib/hostapd/ctrl_iface.h b/contrib/hostapd/ctrl_iface.h deleted file mode 100644 index 2ac2f3b29931..000000000000 --- a/contrib/hostapd/ctrl_iface.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * hostapd / UNIX domain socket -based control interface - * Copyright (c) 2004, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 - -int hostapd_ctrl_iface_init(struct hostapd_data *hapd); -void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd); -void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level, - char *buf, size_t len); - -#endif /* CTRL_IFACE_H */ diff --git a/contrib/hostapd/defconfig b/contrib/hostapd/defconfig deleted file mode 100644 index 634f7f5fce8d..000000000000 --- a/contrib/hostapd/defconfig +++ /dev/null @@ -1,108 +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 - -# Driver interface for wired authenticator -#CONFIG_DRIVER_WIRED=y - -# Driver interface for madwifi driver -#CONFIG_DRIVER_MADWIFI=y -#CFLAGS += -I../head # change to reflect local setup; directory for madwifi src - -# Driver interface for Prism54 driver -#CONFIG_DRIVER_PRISM54=y - -# Driver interface for drivers using Devicescape IEEE 802.11 stack -#CONFIG_DRIVER_DEVICESCAPE=y -# Currently, driver_devicescape.c build requires some additional parameters -# to be able to include some of the kernel header files. Following lines can -# be used to set these (WIRELESS_DEV must point to the root directory of the -# wireless-dev.git tree). -#WIRELESS_DEV=/usr/src/wireless-dev -#CFLAGS += -I$(WIRELESS_DEV)/net/mac80211 - -# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver) -#CONFIG_DRIVER_BSD=y -#CFLAGS += -I/usr/local/include -#LIBS += -L/usr/local/lib - -# 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-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 - -# 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 - -# Use the hostapd's IEEE 802.11 authentication (ACL), but without -# the IEEE 802.11 Management capability -CONFIG_DRIVER_RADIUS_ACL=y diff --git a/contrib/hostapd/defs.h b/contrib/hostapd/defs.h deleted file mode 100644 index 603fc55c110a..000000000000 --- a/contrib/hostapd/defs.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * WPA Supplicant - Common definitions - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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; - - -typedef enum { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP, - WPA_ALG_IGTK, WPA_ALG_DHV } wpa_alg; -typedef enum { CIPHER_NONE, CIPHER_WEP40, CIPHER_TKIP, CIPHER_CCMP, - CIPHER_WEP104 } wpa_cipher; -typedef enum { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE, - KEY_MGMT_802_1X_NO_WPA, KEY_MGMT_WPA_NONE } wpa_key_mgmt; - -/** - * 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. - */ -typedef enum { - /** - * 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_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_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 -} wpa_states; - -#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 - -#endif /* DEFS_H */ diff --git a/contrib/hostapd/des.c b/contrib/hostapd/des.c deleted file mode 100644 index 8e0d56fc6af1..000000000000 --- a/contrib/hostapd/des.c +++ /dev/null @@ -1,476 +0,0 @@ -/* - * DES and 3DES-EDE ciphers - * - * Modifications to LibTomCrypt implementation: - * Copyright (c) 2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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" - - -#ifdef INTERNAL_DES - -/* - * 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]); -} - - -struct des3_key_s { - u32 ek[3][32]; - u32 dk[3][32]; -}; - -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]); -} - -#endif /* INTERNAL_DES */ diff --git a/contrib/hostapd/developer.txt b/contrib/hostapd/developer.txt deleted file mode 100644 index e1d316341390..000000000000 --- a/contrib/hostapd/developer.txt +++ /dev/null @@ -1,219 +0,0 @@ -Developer notes for hostapd -=========================== - -hostapd daemon setup, operations, and shutdown ----------------------------------------------- - -Files: hostapd.[ch] - -Externally called functions: - hostapd_new_assoc_sta() is called when a station associates with the AP - -Event loop functions: - handle_term() is called on SIGINT and SIGTERM to terminate hostapd process - handle_reload() is called on SIGHUP to reload configuration - handle_dump_state() is called on SIGUSR1 to dump station state data to a - text file - hostapd_rotate_wep() is called to periodically change WEP keys - - -Configuration parsing ---------------------- - -Configuration file parsing and data structure definition. - -Files: config.[ch] - -Externally called functions: - hostapd_config_read() is called to read and parse a configuration file; - allocates and returns configuration data structure - hostapd_config_free() is called to free configuration data structure - hostapd_maclist_found() is called to check whether a given address is found - in a list of MAC addresses - - -Kernel driver access --------------------- - -Helper functions for configuring the Host AP kernel driver and -accessing data from it. - -Files: driver.[ch] - - -IEEE 802.11 frame handling (netdevice wlan#ap) ----------------------------------------------- - -Receive all incoming IEEE 802.11 frames from the kernel driver via -wlan#ap interface. - -Files: receive.c - -Externally called functions: - hostapd_init_sockets() is called to initialize sockets for receiving and - sending IEEE 802.11 frames via wlan#ap interface - -Event loop functions: - handle_read() is called for each incoming packet from wlan#ap net device - - -Station table -------------- - -Files: sta_info.[ch], ap.h - -Event loop functions: - ap_handle_timer() is called to check station activity and to remove - inactive stations - - -IEEE 802.11 management ----------------------- - -IEEE 802.11 management frame sending and processing (mainly, -authentication and association). IEEE 802.11 station functionality -(authenticate and associate with another AP as an station). - -Files: ieee802_11.[ch] - -Externally called functions: - ieee802_11_mgmt() is called for each received IEEE 802.11 management frame - (from handle_frame() in hostapd.c) - ieee802_11_mgmt_cb() is called for each received TX callback of IEEE 802.11 - management frame (from handle_tx_callback() in hostapd.c) - ieee802_11_send_deauth() is called to send deauthentication frame - ieee802_11_send_disassoc() is called to send disassociation frame - ieee802_11_parse_elems() is used to parse information elements in - IEEE 802.11 management frames - -Event loop functions: - ieee802_11_sta_authenticate() called to retry authentication (with another - AP) - ieee802_11_sta_associate() called to retry association (with another AP) - - -IEEE 802.11 authentication --------------------------- - -Access control list for IEEE 802.11 authentication. Uses staticly -configured ACL from configuration files or an external RADIUS -server. Results from external RADIUS queries are cached to allow -faster authentication frame processing. - -Files: ieee802_11_auth.[ch] - -Externally called functions: - hostapd_acl_init() called once during hostapd startup - hostapd_acl_deinit() called once during hostapd shutdown - hostapd_acl_recv_radius() called by IEEE 802.1X code for incoming RADIUS - Authentication messages (returns 0 if message was processed) - hostapd_allowed_address() called to check whether a specified station can be - authenticated - -Event loop functions: - hostapd_acl_expire() is called to expire ACL cache entries - - -IEEE 802.1X Authenticator -------------------------- - -Files: ieee802_1x.[ch] - - -Externally called functions: - ieee802_1x_receive() is called for each incoming EAPOL frame from the - wireless interface - ieee802_1x_new_station() is called to start IEEE 802.1X authentication when - a new station completes IEEE 802.11 association - -Event loop functions: - ieee802_1x_receive_auth() called for each incoming RADIUS Authentication - message - - -EAPOL state machine -------------------- - -IEEE 802.1X state machine for EAPOL. - -Files: eapol_sm.[ch] - -Externally called functions: - eapol_sm_step() is called to advance EAPOL state machines after any change - that could affect their state - -Event loop functions: - eapol_port_timers_tick() called once per second to advance Port Timers state - machine - - -IEEE 802.11f (IAPP) -------------------- - -Files: iapp.[ch] - -Externally called functions: - iapp_new_station() is called to start accounting session when a new station - completes IEEE 802.11 association or IEEE 802.1X authentication - -Event loop functions: - iapp_receive_udp() is called for incoming IAPP frames over UDP - - -Per station accounting ----------------------- - -Send RADIUS Accounting start and stop messages to a RADIUS Accounting -server. Process incoming RADIUS Accounting messages. - -Files: accounting.[ch] - -Externally called functions: - accounting_init() called once during hostapd startup - accounting_deinit() called once during hostapd shutdown - accounting_sta_start() called when a station starts new session - accounting_sta_stop() called when a station session is terminated - -Event loop functions: - accounting_receive() called for each incoming RADIUS Accounting message - accounting_list_timer() called to retransmit accounting messages and to - remove expired entries - - -RADIUS messages ---------------- - -RADIUS message generation and parsing functions. - -Files: radius.[ch] - - -Event loop ----------- - -Event loop for registering timeout calls, signal handlers, and socket -read events. - -Files: eloop.[ch] - - -RC4 ---- - -RC4 encryption - -Files: rc4.[ch] - - -MD5 ---- - -MD5 hash and HMAC-MD5. - -Files: md5.[ch] - - -Miscellaneous helper functions ------------------------------- - -Files: common.[ch] diff --git a/contrib/hostapd/doc/code_structure.doxygen b/contrib/hostapd/doc/code_structure.doxygen deleted file mode 100644 index fdcf725b5d7f..000000000000 --- a/contrib/hostapd/doc/code_structure.doxygen +++ /dev/null @@ -1,5 +0,0 @@ -/** -\page code_structure Structure of the source code - - -*/ diff --git a/contrib/hostapd/doc/ctrl_iface.doxygen b/contrib/hostapd/doc/ctrl_iface.doxygen deleted file mode 100644 index 76cfc6a6b79c..000000000000 --- a/contrib/hostapd/doc/ctrl_iface.doxygen +++ /dev/null @@ -1,66 +0,0 @@ -/** -\page ctrl_iface_page Control interface - -hostapd implements a control interface that can be used by -external programs to control the operations of the hostapd -daemon and to get status information and event notifications. There is -a small C library, in a form of a single C file, wpa_ctrl.c, that -provides helper functions to facilitate the use of the control -interface. External programs can link this file into them and then use -the library functions documented in wpa_ctrl.h to interact with -%wpa_supplicant. This library can also be used with C++. hostapd_cli.c -is an example program using this library. - -There are multiple mechanisms for inter-process communication. For -example, Linux version of hostapd is using UNIX domain sockets for the -control interface. The use of the functions defined in wpa_ctrl.h can -be used to hide the details of the used IPC from external programs. - - -\section using_ctrl_iface Using the control interface - -External programs, e.g., a GUI or a configuration utility, that need to -communicate with hostapd should link in wpa_ctrl.c. This -allows them to use helper functions to open connection to the control -interface with wpa_ctrl_open() and to send commands with -wpa_ctrl_request(). - -hostapd uses the control interface for two types of communication: -commands and unsolicited event messages. Commands are a pair of -messages, a request from the external program and a response from -hostapd. These can be executed using wpa_ctrl_request(). -Unsolicited event messages are sent by hostapd to the control -interface connection without specific request from the external program -for receiving each message. However, the external program needs to -attach to the control interface with wpa_ctrl_attach() to receive these -unsolicited messages. - -If the control interface connection is used both for commands and -unsolicited event messages, there is potential for receiving an -unsolicited message between the command request and response. -wpa_ctrl_request() caller will need to supply a callback, msg_cb, -for processing these messages. Often it is easier to open two -control interface connections by calling wpa_ctrl_open() twice and -then use one of the connections for commands and the other one for -unsolicited messages. This way command request/response pairs will -not be broken by unsolicited messages. wpa_cli is an example of how -to use only one connection for both purposes and wpa_gui demonstrates -how to use two separate connections. - -Once the control interface connection is not needed anymore, it should -be closed by calling wpa_ctrl_close(). If the connection was used for -unsolicited event messages, it should be first detached by calling -wpa_ctrl_detach(). - - -\section ctrl_iface_cmds Control interface commands - -Following commands can be used with wpa_ctrl_request(): - -\subsection ctrl_iface_PING PING - -This command can be used to test whether hostapd is replying -to the control interface commands. The expected reply is \c PONG if the -connection is open and hostapd is processing commands. - -*/ diff --git a/contrib/hostapd/doc/doxygen.fast b/contrib/hostapd/doc/doxygen.fast deleted file mode 100644 index 44760f4204b3..000000000000 --- a/contrib/hostapd/doc/doxygen.fast +++ /dev/null @@ -1,233 +0,0 @@ -# Doxyfile 1.4.4 - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- -PROJECT_NAME = hostapd -PROJECT_NUMBER = 0.5.x -OUTPUT_DIRECTORY = doc -CREATE_SUBDIRS = NO -OUTPUT_LANGUAGE = English -USE_WINDOWS_ENCODING = NO -BRIEF_MEMBER_DESC = YES -REPEAT_BRIEF = YES -ABBREVIATE_BRIEF = "The $name class" \ - "The $name widget" \ - "The $name file" \ - is \ - provides \ - specifies \ - contains \ - represents \ - a \ - an \ - the -ALWAYS_DETAILED_SEC = NO -INLINE_INHERITED_MEMB = NO -FULL_PATH_NAMES = YES -STRIP_FROM_PATH = -STRIP_FROM_INC_PATH = -SHORT_NAMES = NO -JAVADOC_AUTOBRIEF = NO -MULTILINE_CPP_IS_BRIEF = NO -DETAILS_AT_TOP = NO -INHERIT_DOCS = YES -DISTRIBUTE_GROUP_DOC = NO -SEPARATE_MEMBER_PAGES = NO -TAB_SIZE = 8 -ALIASES = -OPTIMIZE_OUTPUT_FOR_C = YES -OPTIMIZE_OUTPUT_JAVA = NO -SUBGROUPING = YES -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- -EXTRACT_ALL = NO -EXTRACT_PRIVATE = NO -EXTRACT_STATIC = NO -EXTRACT_LOCAL_CLASSES = YES -EXTRACT_LOCAL_METHODS = NO -HIDE_UNDOC_MEMBERS = NO -HIDE_UNDOC_CLASSES = NO -HIDE_FRIEND_COMPOUNDS = NO -HIDE_IN_BODY_DOCS = NO -INTERNAL_DOCS = NO -CASE_SENSE_NAMES = YES -HIDE_SCOPE_NAMES = NO -SHOW_INCLUDE_FILES = YES -INLINE_INFO = YES -SORT_MEMBER_DOCS = YES -SORT_BRIEF_DOCS = NO -SORT_BY_SCOPE_NAME = NO -GENERATE_TODOLIST = YES -GENERATE_TESTLIST = YES -GENERATE_BUGLIST = YES -GENERATE_DEPRECATEDLIST= YES -ENABLED_SECTIONS = -MAX_INITIALIZER_LINES = 30 -SHOW_USED_FILES = YES -SHOW_DIRECTORIES = NO -FILE_VERSION_FILTER = -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- -QUIET = NO -WARNINGS = YES -WARN_IF_UNDOCUMENTED = YES -WARN_IF_DOC_ERROR = YES -WARN_NO_PARAMDOC = YES -WARN_FORMAT = "$file:$line: $text" -WARN_LOGFILE = -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- -INPUT = . \ - ../wpa_supplicant/eap_sim_common.c \ - ../wpa_supplicant/eap_sim_common.h -FILE_PATTERNS = *.c *.h *.doxygen -RECURSIVE = YES -EXCLUDE = -EXCLUDE_SYMLINKS = NO -EXCLUDE_PATTERNS = -EXAMPLE_PATH = -EXAMPLE_PATTERNS = * -EXAMPLE_RECURSIVE = NO -IMAGE_PATH = doc -INPUT_FILTER = doc/kerneldoc2doxygen.pl -FILTER_PATTERNS = -FILTER_SOURCE_FILES = YES -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- -SOURCE_BROWSER = YES -INLINE_SOURCES = NO -STRIP_CODE_COMMENTS = YES -REFERENCED_BY_RELATION = NO -REFERENCES_RELATION = NO -VERBATIM_HEADERS = NO -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- -ALPHABETICAL_INDEX = YES -COLS_IN_ALPHA_INDEX = 3 -IGNORE_PREFIX = -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- -GENERATE_HTML = YES -HTML_OUTPUT = html -HTML_FILE_EXTENSION = .html -HTML_HEADER = -HTML_FOOTER = -HTML_STYLESHEET = -HTML_ALIGN_MEMBERS = YES -GENERATE_HTMLHELP = NO -CHM_FILE = -HHC_LOCATION = -GENERATE_CHI = NO -BINARY_TOC = NO -TOC_EXPAND = NO -DISABLE_INDEX = NO -ENUM_VALUES_PER_LINE = 4 -GENERATE_TREEVIEW = NO -TREEVIEW_WIDTH = 250 -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- -GENERATE_LATEX = NO -LATEX_OUTPUT = latex -LATEX_CMD_NAME = latex -MAKEINDEX_CMD_NAME = makeindex -COMPACT_LATEX = NO -PAPER_TYPE = a4wide -EXTRA_PACKAGES = -LATEX_HEADER = -PDF_HYPERLINKS = YES -USE_PDFLATEX = YES -LATEX_BATCHMODE = NO -LATEX_HIDE_INDICES = NO -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- -GENERATE_RTF = NO -RTF_OUTPUT = rtf -COMPACT_RTF = NO -RTF_HYPERLINKS = NO -RTF_STYLESHEET_FILE = -RTF_EXTENSIONS_FILE = -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- -GENERATE_MAN = NO -MAN_OUTPUT = man -MAN_EXTENSION = .3 -MAN_LINKS = NO -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- -GENERATE_XML = NO -XML_OUTPUT = xml -XML_SCHEMA = -XML_DTD = -XML_PROGRAMLISTING = YES -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- -GENERATE_AUTOGEN_DEF = NO -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- -GENERATE_PERLMOD = NO -PERLMOD_LATEX = NO -PERLMOD_PRETTY = YES -PERLMOD_MAKEVAR_PREFIX = -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- -ENABLE_PREPROCESSING = YES -MACRO_EXPANSION = NO -EXPAND_ONLY_PREDEF = NO -SEARCH_INCLUDES = YES -INCLUDE_PATH = -INCLUDE_FILE_PATTERNS = -PREDEFINED = RADIUS_SERVER EAP_SERVER EAP_SIM -EXPAND_AS_DEFINED = -SKIP_FUNCTION_MACROS = YES -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- -TAGFILES = -GENERATE_TAGFILE = -ALLEXTERNALS = NO -EXTERNAL_GROUPS = YES -PERL_PATH = /usr/bin/perl -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- -CLASS_DIAGRAMS = NO -HIDE_UNDOC_RELATIONS = YES -HAVE_DOT = NO -CLASS_GRAPH = YES -COLLABORATION_GRAPH = YES -GROUP_GRAPHS = YES -UML_LOOK = NO -TEMPLATE_RELATIONS = NO -INCLUDE_GRAPH = YES -INCLUDED_BY_GRAPH = YES -CALL_GRAPH = YES -GRAPHICAL_HIERARCHY = YES -DIRECTORY_GRAPH = NO -DOT_IMAGE_FORMAT = png -DOT_PATH = -DOTFILE_DIRS = -MAX_DOT_GRAPH_WIDTH = 1024 -MAX_DOT_GRAPH_HEIGHT = 1024 -MAX_DOT_GRAPH_DEPTH = 1000 -DOT_TRANSPARENT = NO -DOT_MULTI_TARGETS = NO -GENERATE_LEGEND = YES -DOT_CLEANUP = YES -#--------------------------------------------------------------------------- -# Configuration::additions related to the search engine -#--------------------------------------------------------------------------- -SEARCHENGINE = NO diff --git a/contrib/hostapd/doc/doxygen.full b/contrib/hostapd/doc/doxygen.full deleted file mode 100644 index 619f977303da..000000000000 --- a/contrib/hostapd/doc/doxygen.full +++ /dev/null @@ -1,230 +0,0 @@ -# Doxyfile 1.4.1 - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- -PROJECT_NAME = hostapd -PROJECT_NUMBER = 0.5.x -OUTPUT_DIRECTORY = doc -CREATE_SUBDIRS = NO -OUTPUT_LANGUAGE = English -USE_WINDOWS_ENCODING = NO -BRIEF_MEMBER_DESC = YES -REPEAT_BRIEF = YES -ABBREVIATE_BRIEF = "The $name class" \ - "The $name widget" \ - "The $name file" \ - is \ - provides \ - specifies \ - contains \ - represents \ - a \ - an \ - the -ALWAYS_DETAILED_SEC = NO -INLINE_INHERITED_MEMB = NO -FULL_PATH_NAMES = YES -STRIP_FROM_PATH = -STRIP_FROM_INC_PATH = -SHORT_NAMES = NO -JAVADOC_AUTOBRIEF = NO -MULTILINE_CPP_IS_BRIEF = NO -DETAILS_AT_TOP = NO -INHERIT_DOCS = YES -DISTRIBUTE_GROUP_DOC = NO -TAB_SIZE = 8 -ALIASES = -OPTIMIZE_OUTPUT_FOR_C = YES -OPTIMIZE_OUTPUT_JAVA = NO -SUBGROUPING = YES -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- -EXTRACT_ALL = NO -EXTRACT_PRIVATE = NO -EXTRACT_STATIC = NO -EXTRACT_LOCAL_CLASSES = YES -EXTRACT_LOCAL_METHODS = NO -HIDE_UNDOC_MEMBERS = NO -HIDE_UNDOC_CLASSES = NO -HIDE_FRIEND_COMPOUNDS = NO -HIDE_IN_BODY_DOCS = NO -INTERNAL_DOCS = NO -CASE_SENSE_NAMES = YES -HIDE_SCOPE_NAMES = NO -SHOW_INCLUDE_FILES = YES -INLINE_INFO = YES -SORT_MEMBER_DOCS = YES -SORT_BRIEF_DOCS = NO -SORT_BY_SCOPE_NAME = NO -GENERATE_TODOLIST = YES -GENERATE_TESTLIST = YES -GENERATE_BUGLIST = YES -GENERATE_DEPRECATEDLIST= YES -ENABLED_SECTIONS = -MAX_INITIALIZER_LINES = 30 -SHOW_USED_FILES = YES -SHOW_DIRECTORIES = NO -FILE_VERSION_FILTER = -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- -QUIET = NO -WARNINGS = YES -WARN_IF_UNDOCUMENTED = YES -WARN_IF_DOC_ERROR = YES -WARN_NO_PARAMDOC = YES -WARN_FORMAT = "$file:$line: $text" -WARN_LOGFILE = -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- -INPUT = . -FILE_PATTERNS = *.c *.h *.doxygen -RECURSIVE = YES -EXCLUDE = -EXCLUDE_SYMLINKS = NO -EXCLUDE_PATTERNS = -EXAMPLE_PATH = -EXAMPLE_PATTERNS = * -EXAMPLE_RECURSIVE = NO -IMAGE_PATH = doc -INPUT_FILTER = kerneldoc2doxygen.pl -FILTER_PATTERNS = -FILTER_SOURCE_FILES = YES -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- -SOURCE_BROWSER = YES -INLINE_SOURCES = NO -STRIP_CODE_COMMENTS = YES -REFERENCED_BY_RELATION = NO -REFERENCES_RELATION = NO -VERBATIM_HEADERS = NO -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- -ALPHABETICAL_INDEX = YES -COLS_IN_ALPHA_INDEX = 3 -IGNORE_PREFIX = -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- -GENERATE_HTML = YES -HTML_OUTPUT = html -HTML_FILE_EXTENSION = .html -HTML_HEADER = -HTML_FOOTER = -HTML_STYLESHEET = -HTML_ALIGN_MEMBERS = YES -GENERATE_HTMLHELP = NO -CHM_FILE = -HHC_LOCATION = -GENERATE_CHI = NO -BINARY_TOC = NO -TOC_EXPAND = NO -DISABLE_INDEX = NO -ENUM_VALUES_PER_LINE = 4 -GENERATE_TREEVIEW = NO -TREEVIEW_WIDTH = 250 -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- -GENERATE_LATEX = YES -LATEX_OUTPUT = latex -LATEX_CMD_NAME = latex -MAKEINDEX_CMD_NAME = makeindex -COMPACT_LATEX = NO -PAPER_TYPE = a4wide -EXTRA_PACKAGES = -LATEX_HEADER = -PDF_HYPERLINKS = YES -USE_PDFLATEX = YES -LATEX_BATCHMODE = NO -LATEX_HIDE_INDICES = NO -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- -GENERATE_RTF = NO -RTF_OUTPUT = rtf -COMPACT_RTF = NO -RTF_HYPERLINKS = NO -RTF_STYLESHEET_FILE = -RTF_EXTENSIONS_FILE = -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- -GENERATE_MAN = NO -MAN_OUTPUT = man -MAN_EXTENSION = .3 -MAN_LINKS = NO -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- -GENERATE_XML = NO -XML_OUTPUT = xml -XML_SCHEMA = -XML_DTD = -XML_PROGRAMLISTING = YES -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- -GENERATE_AUTOGEN_DEF = NO -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- -GENERATE_PERLMOD = NO -PERLMOD_LATEX = NO -PERLMOD_PRETTY = YES -PERLMOD_MAKEVAR_PREFIX = -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- -ENABLE_PREPROCESSING = YES -MACRO_EXPANSION = NO -EXPAND_ONLY_PREDEF = NO -SEARCH_INCLUDES = YES -INCLUDE_PATH = -INCLUDE_FILE_PATTERNS = -PREDEFINED = RADIUS_SERVER EAP_SERVER EAP_SIM -EXPAND_AS_DEFINED = -SKIP_FUNCTION_MACROS = YES -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- -TAGFILES = -GENERATE_TAGFILE = -ALLEXTERNALS = NO -EXTERNAL_GROUPS = YES -PERL_PATH = /usr/bin/perl -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- -CLASS_DIAGRAMS = NO -HIDE_UNDOC_RELATIONS = YES -HAVE_DOT = YES -CLASS_GRAPH = YES -COLLABORATION_GRAPH = YES -GROUP_GRAPHS = YES -UML_LOOK = NO -TEMPLATE_RELATIONS = NO -INCLUDE_GRAPH = YES -INCLUDED_BY_GRAPH = YES -CALL_GRAPH = YES -GRAPHICAL_HIERARCHY = YES -DIRECTORY_GRAPH = NO -DOT_IMAGE_FORMAT = png -DOT_PATH = -DOTFILE_DIRS = -MAX_DOT_GRAPH_WIDTH = 1024 -MAX_DOT_GRAPH_HEIGHT = 1024 -MAX_DOT_GRAPH_DEPTH = 1000 -DOT_TRANSPARENT = NO -DOT_MULTI_TARGETS = NO -GENERATE_LEGEND = YES -DOT_CLEANUP = YES -#--------------------------------------------------------------------------- -# Configuration::additions related to the search engine -#--------------------------------------------------------------------------- -SEARCHENGINE = YES diff --git a/contrib/hostapd/doc/driver_wrapper.doxygen b/contrib/hostapd/doc/driver_wrapper.doxygen deleted file mode 100644 index 0ad196f2d6b6..000000000000 --- a/contrib/hostapd/doc/driver_wrapper.doxygen +++ /dev/null @@ -1,20 +0,0 @@ -/** -\page driver_wrapper Driver wrapper implementation (driver.h, drivers.c) - -All hardware and driver dependent functionality is in separate C files -that implement defined wrapper functions. Other parts -of the hostapd are designed to be hardware, driver, and operating -system independent. - -Driver wrappers need to implement whatever calls are used in the -target operating system/driver for controlling wireless LAN -devices. As an example, in case of Linux, these are mostly some glue -code and ioctl() calls and netlink message parsing for Linux Wireless -Extensions (WE). Since features required for WPA were added only recently to -Linux Wireless Extensions (in version 18), some driver specific code is used -in number of driver interface implementations. These driver dependent parts -can be replaced with generic code in driver_wext.c once the target driver -includes full support for WE-18. After that, all Linux drivers, at -least in theory, could use the same driver wrapper code. - -*/ diff --git a/contrib/hostapd/doc/eap.doxygen b/contrib/hostapd/doc/eap.doxygen deleted file mode 100644 index f0f135aa9598..000000000000 --- a/contrib/hostapd/doc/eap.doxygen +++ /dev/null @@ -1,56 +0,0 @@ -/** -\page eap_module EAP server implementation - -Extensible Authentication Protocol (EAP) is an authentication framework -defined in RFC 3748. hostapd uses a separate code module for EAP server -implementation. This module was designed to use only a minimal set of -direct function calls (mainly, to debug/event functions) in order for -it to be usable in other programs. The design of the EAP -implementation is based loosely on RFC 4137. The state machine is -defined in this RFC and so is the interface between the server state -machine and methods. As such, this RFC provides useful information for -understanding the EAP server implementation in hostapd. - -Some of the terminology used in EAP state machine is referring to -EAPOL (IEEE 802.1X), but there is no strict requirement on the lower -layer being IEEE 802.1X if EAP module is built for other programs than -%wpa_supplicant. These terms should be understood to refer to the -lower layer as defined in RFC 4137. - - -\section adding_eap_methods Adding EAP methods - -Each EAP method is implemented as a separate module, usually as one C -file named eap_<name of the method>.c, e.g., eap_md5.c. All EAP -methods use the same interface between the server state machine and -method specific functions. This allows new EAP methods to be added -without modifying the core EAP state machine implementation. - -New EAP methods need to be registered by adding them into the build -(Makefile) and the EAP method registration list in the -eap_server_register_methods() function of eap_methods.c. Each EAP -method should use a build-time configuration option, e.g., EAP_TLS, in -order to make it possible to select which of the methods are included -in the build. - -EAP methods must implement the interface defined in eap_i.h. struct -eap_method defines the needed function pointers that each EAP method -must provide. In addition, the EAP type and name are registered using -this structure. This interface is based on section 4.4 of RFC 4137. - -It is recommended that the EAP methods would use generic helper -functions, eap_msg_alloc() and eap_hdr_validate() when processing -messages. This allows code sharing and can avoid missing some of the -needed validation steps for received packets. In addition, these -functions make it easier to change between expanded and legacy EAP -header, if needed. - -When adding an EAP method that uses a vendor specific EAP type -(Expanded Type as defined in RFC 3748, Chapter 5.7), the new method -must be registered by passing vendor id instead of EAP_VENDOR_IETF to -eap_server_method_alloc(). These methods must not try to emulate -expanded types by registering a legacy EAP method for type 254. See -eap_vendor_test.c for an example of an EAP method implementation that -is implemented as an expanded type. - -*/ diff --git a/contrib/hostapd/doc/hostapd.fig b/contrib/hostapd/doc/hostapd.fig deleted file mode 100644 index af3f0be19a9b..000000000000 --- a/contrib/hostapd/doc/hostapd.fig +++ /dev/null @@ -1,264 +0,0 @@ -#FIG 3.2 -Landscape -Center -Inches -Letter -100.00 -Single --2 -1200 2 -6 1875 4050 2925 4350 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 1875 4050 2925 4050 2925 4350 1875 4350 1875 4050 -4 0 0 50 -1 0 12 0.0000 4 180 735 2025 4275 l2_packet\001 --6 -6 4725 1200 5925 1500 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 4725 1200 5925 1200 5925 1500 4725 1500 4725 1200 -4 0 0 50 -1 0 12 0.0000 4 135 1005 4800 1425 GUI frontend\001 --6 -6 6000 2700 7200 3225 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 6000 2700 7200 2700 7200 3225 6000 3225 6000 2700 -4 0 0 50 -1 0 12 0.0000 4 135 975 6075 2925 WPA/WPA2\001 -4 0 0 50 -1 0 12 0.0000 4 135 1065 6075 3150 state machine\001 --6 -6 6000 4950 7200 5475 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 6000 4950 7200 4950 7200 5475 6000 5475 6000 4950 -4 0 0 50 -1 0 12 0.0000 4 135 360 6075 5175 EAP\001 -4 0 0 50 -1 0 12 0.0000 4 135 1065 6075 5400 state machine\001 --6 -6 4350 3900 5025 4425 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 4350 3900 5025 3900 5025 4425 4350 4425 4350 3900 -4 0 0 50 -1 0 12 0.0000 4 105 420 4500 4125 event\001 -4 0 0 50 -1 0 12 0.0000 4 180 315 4500 4350 loop\001 --6 -6 4275 2550 5100 2850 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 4275 2550 5100 2550 5100 2850 4275 2850 4275 2550 -4 0 0 50 -1 0 12 0.0000 4 135 450 4425 2775 ctrl i/f\001 --6 -6 6000 3900 7200 4425 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 6000 3900 7200 3900 7200 4425 6000 4425 6000 3900 -4 0 0 50 -1 0 12 0.0000 4 135 600 6075 4125 EAPOL\001 -4 0 0 50 -1 0 12 0.0000 4 135 1065 6075 4350 state machine\001 --6 -6 2775 3150 4050 3450 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 2775 3150 4050 3150 4050 3450 2775 3450 2775 3150 -4 0 0 50 -1 0 12 0.0000 4 180 990 2925 3375 configuration\001 --6 -6 3450 1200 4575 1500 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 3450 1200 4575 1200 4575 1500 3450 1500 3450 1200 -4 0 0 50 -1 0 12 0.0000 4 180 870 3600 1425 hostapd_cli\001 --6 -6 3525 7800 5775 8100 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 3525 7800 5775 7800 5775 8100 3525 8100 3525 7800 -4 0 0 50 -1 0 12 0.0000 4 135 2145 3600 8025 kernel network device driver\001 --6 -6 4275 6000 5100 6300 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 4275 6000 5100 6000 5100 6300 4275 6300 4275 6000 -4 0 0 50 -1 0 12 0.0000 4 135 630 4350 6225 driver i/f\001 --6 -6 8175 4725 9225 5025 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8175 4725 9225 4725 9225 5025 8175 5025 8175 4725 -4 0 0 50 -1 0 12 0.0000 4 135 735 8250 4950 EAP-TLS\001 --6 -6 9300 4725 10350 5025 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 9300 4725 10350 4725 10350 5025 9300 5025 9300 4725 -4 0 0 50 -1 0 12 0.0000 4 135 810 9375 4950 EAP-MD5\001 --6 -6 8175 5100 9225 5400 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8175 5100 9225 5100 9225 5400 8175 5400 8175 5100 -4 0 0 50 -1 0 12 0.0000 4 135 885 8250 5325 EAP-PEAP\001 --6 -6 9300 5100 10350 5400 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 9300 5100 10350 5100 10350 5400 9300 5400 9300 5100 -4 0 0 50 -1 0 12 0.0000 4 135 840 9375 5325 EAP-TTLS\001 --6 -6 8175 5475 9225 5775 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8175 5475 9225 5475 9225 5775 8175 5775 8175 5475 -4 0 0 50 -1 0 12 0.0000 4 135 780 8250 5700 EAP-GTC\001 --6 -6 8175 5850 9225 6150 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8175 5850 9225 5850 9225 6150 8175 6150 8175 5850 -4 0 0 50 -1 0 12 0.0000 4 135 750 8250 6075 EAP-SIM\001 --6 -6 8175 6225 9225 6525 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8175 6225 9225 6225 9225 6525 8175 6525 8175 6225 -4 0 0 50 -1 0 12 0.0000 4 135 765 8250 6450 EAP-PSK\001 --6 -6 9300 5850 10350 6150 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 9300 5850 10350 5850 10350 6150 9300 6150 9300 5850 -4 0 0 50 -1 0 12 0.0000 4 135 825 9375 6075 EAP-AKA\001 --6 -6 9300 5475 10350 5775 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 9300 5475 10350 5475 10350 5775 9300 5775 9300 5475 -4 0 0 50 -1 0 12 0.0000 4 135 795 9375 5700 EAP-PAX\001 --6 -6 8175 6600 9675 6900 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8175 6600 9675 6600 9675 6900 8175 6900 8175 6600 -4 0 0 50 -1 0 12 0.0000 4 135 1365 8250 6825 EAP-MSCHAPv2\001 --6 -6 8700 3450 9375 3750 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8700 3450 9375 3450 9375 3750 8700 3750 8700 3450 -4 0 0 50 -1 0 12 0.0000 4 150 480 8775 3675 crypto\001 --6 -6 9600 3450 10275 3750 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 9600 3450 10275 3450 10275 3750 9600 3750 9600 3450 -4 0 0 50 -1 0 12 0.0000 4 135 315 9750 3675 TLS\001 --6 -6 6000 5775 7200 6300 -6 6000 5775 7200 6300 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 6000 5775 7200 5775 7200 6300 6000 6300 6000 5775 -4 0 0 50 -1 0 12 0.0000 4 135 690 6075 6000 RADIUS\001 --6 -4 0 0 50 -1 0 12 0.0000 4 90 480 6075 6225 server\001 --6 -6 8100 2250 8925 2775 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8100 2250 8925 2250 8925 2775 8100 2775 8100 2250 -4 0 0 50 -1 0 12 0.0000 4 135 690 8175 2475 RADIUS\001 -4 0 0 50 -1 0 12 0.0000 4 135 420 8175 2700 client\001 --6 -6 3150 5475 4425 5775 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 3150 5475 4425 5475 4425 5775 3150 5775 3150 5475 -4 0 0 50 -1 0 12 0.0000 4 135 990 3300 5700 driver events\001 --6 -6 1950 5550 2625 6075 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 1950 5550 2625 5550 2625 6075 1950 6075 1950 5550 -4 0 0 50 -1 0 12 0.0000 4 135 540 2025 5775 Station\001 -4 0 0 50 -1 0 12 0.0000 4 135 375 2025 6000 table\001 --6 -6 1875 4725 2925 5250 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 1875 4725 2925 4725 2925 5250 1875 5250 1875 4725 -4 0 0 50 -1 0 12 0.0000 4 135 960 1950 4950 IEEE 802.11\001 -4 0 0 50 -1 0 12 0.0000 4 135 555 1950 5175 MLME\001 --6 -2 1 1 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 - 1275 4200 1875 4200 -2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 - 4500 2550 3900 1500 -2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 - 4800 2550 5400 1500 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 2925 4200 4350 4200 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 5025 3900 6000 3000 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 5025 4200 6000 4200 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 4650 6000 4650 4425 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 6600 4425 6600 4950 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 6600 3225 6600 3900 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 7200 5250 8100 5250 -2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 9075 4425 9075 3750 -2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 7200 3000 8700 3525 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 4650 3900 4650 2850 -2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 7200 4125 8700 3675 -2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 6000 4350 5025 6000 -2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 6000 3150 4875 6000 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 1500 2100 10800 2100 10800 7500 1500 7500 1500 2100 -2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 9900 4425 9900 3750 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 1 - 4350 3900 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 4350 3900 4050 3450 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 4350 4425 4050 5475 -2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 - 2250 7200 4200 7800 -2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 - 7200 7200 5100 7800 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 2775 6900 3675 6900 3675 7200 2775 7200 2775 6900 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 3750 6900 4650 6900 4650 7200 3750 7200 3750 6900 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 - 2250 6900 2250 6600 7200 6600 7200 6900 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 3225 6900 3225 6600 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 4200 6900 4200 6600 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 5175 6900 5175 6600 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 6150 6900 6150 6600 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 4650 6600 4650 6300 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 1800 6900 2700 6900 2700 7200 1800 7200 1800 6900 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 4725 6900 5625 6900 5625 7200 4725 7200 4725 6900 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 5700 6900 6600 6900 6600 7200 5700 7200 5700 6900 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 6675 6900 7800 6900 7800 7200 6675 7200 6675 6900 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8100 6975 10425 6975 10425 4425 8100 4425 8100 6975 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 6600 5475 6600 5775 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 5025 4425 6000 5775 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 3 - 4800 3900 5925 2550 8100 2550 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 7200 3900 8475 2775 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 9450 2250 10425 2250 10425 2775 9450 2775 9450 2250 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 8925 2475 9450 2475 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 2325 5550 2325 5250 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 2925 4950 4350 4275 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 3 - 2850 4725 5775 2400 8100 2400 -4 0 0 50 -1 0 12 0.0000 4 135 915 375 3975 EAPOL and\001 -4 0 0 50 -1 0 12 0.0000 4 180 630 375 4200 pre-auth\001 -4 0 0 50 -1 0 12 0.0000 4 180 810 375 4425 ethertypes\001 -4 0 0 50 -1 0 12 0.0000 4 135 1050 375 4650 from/to kernel\001 -4 0 0 50 -1 0 12 0.0000 4 135 1920 3675 1875 frontend control interface\001 -4 0 0 50 -1 2 14 0.0000 4 195 720 1637 2371 hostapd\001 -4 0 0 50 -1 0 12 0.0000 4 180 600 3825 7125 prism54\001 -4 0 0 50 -1 0 12 0.0000 4 180 510 1875 7125 hostap\001 -4 0 0 50 -1 0 12 0.0000 4 135 600 2850 7125 madwifi\001 -4 0 0 50 -1 0 12 0.0000 4 135 270 4800 7125 bsd\001 -4 0 0 50 -1 0 12 0.0000 4 105 300 6750 7125 test\001 -4 0 0 50 -1 0 12 0.0000 4 135 420 5775 7125 wired\001 -4 0 0 50 -1 0 12 0.0000 4 135 1050 8700 4650 EAP methods\001 -4 0 0 50 -1 0 12 0.0000 4 135 690 9525 2475 RADIUS\001 -4 0 0 50 -1 0 12 0.0000 4 180 825 9525 2700 accounting\001 diff --git a/contrib/hostapd/doc/kerneldoc2doxygen.pl b/contrib/hostapd/doc/kerneldoc2doxygen.pl deleted file mode 100755 index 68835a1ddd31..000000000000 --- a/contrib/hostapd/doc/kerneldoc2doxygen.pl +++ /dev/null @@ -1,129 +0,0 @@ -#!/usr/bin/perl -w -# -########################################################################## -# Convert kernel-doc style comments to Doxygen comments. -########################################################################## -# -# This script reads a C source file from stdin, and writes -# to stdout. Normal usage: -# -# $ mv file.c file.c.gtkdoc -# $ kerneldoc2doxygen.pl <file.c.gtkdoc >file.c -# -# Or to do the same thing with multiple files: -# $ perl -i.gtkdoc kerneldoc2doxygen.pl *.c *.h -# -# This script may also be suitable for use as a Doxygen input filter, -# but that has not been tested. -# -# Back up your source files before using this script!! -# -########################################################################## -# Copyright (C) 2003 Jonathan Foster <jon@jon-foster.co.uk> -# Copyright (C) 2005 Jouni Malinen <j@w1.fi> -# (modified for kerneldoc format used in wpa_supplicant) -# -# This program is free software; you can 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 -# or look at http://www.gnu.org/licenses/gpl.html -########################################################################## - - -########################################################################## -# -# This function converts a single comment from gtk-doc to Doxygen format. -# The parameter does not include the opening or closing lines -# (i.e. given a comment like this: -# "/**\n" -# " * FunctionName:\n" -# " * @foo: This describes the foo parameter\n" -# " * @bar: This describes the bar parameter\n" -# " * @Returns: This describes the return value\n" -# " *\n" -# " * This describes the function.\n" -# " */\n" -# This function gets: -# " * FunctionName:\n" -# " * @foo: This describes the foo parameter\n" -# " * @bar: This describes the bar parameter\n" -# " * @Returns: This describes the return value\n" -# " *\n" -# " * This describes the function.\n" -# And it returns: -# " * This describes the function.\n" -# " *\n" -# " * @param foo This describes the foo parameter\n" -# " * @param bar This describes the bar parameter\n" -# " * @return This describes the return value\n" -# ) -# -sub fixcomment { - $t = $_[0]; - - # " * func: foo" --> "\brief foo\n" - # " * struct bar: foo" --> "\brief foo\n" - # If this fails, not a kernel-doc comment ==> return unmodified. - ($t =~ s/^[\t ]*\*[\t ]*(struct )?([^ \t\n]*) - ([^\n]*)/\\brief $3\n/s) - or return $t; - - # " * Returns: foo" --> "\return foo" - $t =~ s/\n[\t ]*\*[\t ]*Returns:/\n\\return/sig; - - # " * @foo: bar" --> "\param foo bar" - # Handle two common typos: No ":", or "," instead of ":". - $t =~ s/\n[\t ]*\*[\t ]*\@([^ :,]*)[:,]?[\t ]*/\n\\param $1 /sg; - - return $t; -} - -########################################################################## -# Start of main code - -# Read entire stdin into memory - one multi-line string. -$_ = do { local $/; <> }; - -s{^/\*\n \*}{/\*\* \\file\n\\brief}; -s{ \* Copyright}{\\par Copyright\nCopyright}; - -# Fix any comments like "/*************" so they don't match. -# "/***" ===> "/* *" -s{/\*\*\*}{/\* \*}gs; - -# The main comment-detection code. -s{ - ( # $1 = Open comment - /\*\* # Open comment - (?!\*) # Do not match /*** (redundant due to fixup above). - [\t ]*\n? # If 1st line is whitespace, match the lot (including the newline). - ) - (.*?) # $2 = Body of comment (multi-line) - ( # $3 = Close comment - ( # If possible, match the whitespace before the close-comment - (?<=\n) # This part only matches after a newline - [\t ]* # Eat whitespace - )? - \*/ # Close comment - ) - } - { - $1 . fixcomment($2) . $3 - }gesx; -# ^^^^ Modes: g - Global, match all occurances. -# e - Evaluate the replacement as an expression. -# s - Single-line - allows the pattern to match across newlines. -# x - eXtended pattern, ignore embedded whitespace -# and allow comments. - -# Write results to stdout -print $_; - diff --git a/contrib/hostapd/doc/mainpage.doxygen b/contrib/hostapd/doc/mainpage.doxygen deleted file mode 100644 index 7cf95de584af..000000000000 --- a/contrib/hostapd/doc/mainpage.doxygen +++ /dev/null @@ -1,52 +0,0 @@ -/** -\mainpage Developers' documentation for hostapd - -hostapd includes IEEE 802.11 access point management (authentication / -association), IEEE 802.1X/WPA/WPA2 Authenticator, EAP server, and -RADIUS authentication server functionality. It can be build with -various configuration option, e.g., a standalone AP management -solution or a RADIUS authentication server with support for number of -EAP methods. - -The goal of this documentation and comments in the source code is to -give enough information for other developers to understand how hostapd -has been implemented, how it can be modified, how new drivers can be -supported, and how hostapd can be ported to other operating -systems. If any information is missing, feel free to contact Jouni -Malinen <j@w1.fi> for more information. Contributions as -patch files are also very welcome at the same address. Please note -that hostapd is licensed under dual license, GPLv2 or BSD at user's -choice. All contributions to hostapd are expected to use compatible -licensing terms. - -The source code and read-only access to hostapd CVS repository -is available from the project home page at -http://hostap.epitest.fi/hostapd/. This developers' documentation -is also available as a PDF file from -http://hostap.epitest.fi/hostapd/hostapd-devel.pdf . - -The design goal for hostapd was to use hardware, driver, and -OS independent, portable C code for all WPA functionality. The source -code is divided into separate C files as shown on the \ref -code_structure "code structure page". All hardware/driver specific -functionality is in separate files that implement a \ref -driver_wrapper "well-defined driver API". Information about porting -to different target boards and operating systems is available on -the \ref porting "porting page". - -EAPOL (IEEE 802.1X) state machines are implemented as a separate -module that interacts with \ref eap_module "EAP server implementation". -Similarly, RADIUS authentication server is in its own separate module. -Both IEEE 802.1X and RADIUS authentication server can use EAP server -functionality. - -hostapd implements a \ref ctrl_iface_page "control interface" that can -be used by external programs to control the operations of the hostapdt -daemon and to get status information and event notifications. There is -a small C library that provides helper functions to facilitate the use -of the control interface. This library can also be used with C++. - -\image html hostapd.png "hostapd modules" -\image latex hostapd.eps "hostapd modules" width=15cm - -*/ diff --git a/contrib/hostapd/doc/porting.doxygen b/contrib/hostapd/doc/porting.doxygen deleted file mode 100644 index 0621791c0be0..000000000000 --- a/contrib/hostapd/doc/porting.doxygen +++ /dev/null @@ -1,5 +0,0 @@ -/** -\page porting Porting to different target boards and operating systems - - -*/ diff --git a/contrib/hostapd/driver.h b/contrib/hostapd/driver.h deleted file mode 100644 index aeefbea1c45d..000000000000 --- a/contrib/hostapd/driver.h +++ /dev/null @@ -1,678 +0,0 @@ -#ifndef DRIVER_H -#define DRIVER_H - -enum hostapd_driver_if_type { - HOSTAPD_IF_VLAN, HOSTAPD_IF_WDS -}; - -struct driver_ops { - const char *name; /* as appears in the config file */ - - int (*init)(struct hostapd_data *hapd); - void (*deinit)(void *priv); - - int (*wireless_event_init)(void *priv); - void (*wireless_event_deinit)(void *priv); - - /** - * set_8021x - enable/disable IEEE 802.1X support - * @ifname: Interface name (for multi-SSID/VLAN support) - * @priv: driver private data - * @enabled: 1 = enable, 0 = disable - * - * Returns: 0 on success, -1 on failure - * - * Configure the kernel driver to enable/disable 802.1X support. - * This may be an empty function if 802.1X support is always enabled. - */ - int (*set_ieee8021x)(const char *ifname, void *priv, int enabled); - - /** - * set_privacy - enable/disable privacy - * @priv: driver private data - * @enabled: 1 = privacy enabled, 0 = disabled - * - * Return: 0 on success, -1 on failure - * - * Configure privacy. - */ - int (*set_privacy)(const char *ifname, void *priv, int enabled); - - int (*set_encryption)(const char *ifname, void *priv, const char *alg, - const u8 *addr, int idx, - const u8 *key, size_t key_len, int txkey); - int (*get_seqnum)(const char *ifname, void *priv, const u8 *addr, - int idx, u8 *seq); - int (*get_seqnum_igtk)(const char *ifname, void *priv, const u8 *addr, - int idx, u8 *seq); - int (*flush)(void *priv); - int (*set_generic_elem)(const char *ifname, void *priv, const u8 *elem, - size_t elem_len); - - int (*read_sta_data)(void *priv, struct hostap_sta_driver_data *data, - const u8 *addr); - int (*send_eapol)(void *priv, const u8 *addr, const u8 *data, - size_t data_len, int encrypt, const u8 *own_addr); - int (*sta_deauth)(void *priv, const u8 *addr, int reason); - int (*sta_disassoc)(void *priv, const u8 *addr, int reason); - int (*sta_remove)(void *priv, const u8 *addr); - int (*get_ssid)(const char *ifname, void *priv, u8 *buf, int len); - int (*set_ssid)(const char *ifname, void *priv, const u8 *buf, - int len); - int (*set_countermeasures)(void *priv, int enabled); - int (*send_mgmt_frame)(void *priv, const void *msg, size_t len, - int flags); - int (*set_assoc_ap)(void *priv, const u8 *addr); - int (*sta_add)(const char *ifname, void *priv, const u8 *addr, u16 aid, - u16 capability, u8 *supp_rates, size_t supp_rates_len, - int flags); - int (*get_inact_sec)(void *priv, const u8 *addr); - int (*sta_clear_stats)(void *priv, const u8 *addr); - - int (*set_freq)(void *priv, int mode, int freq); - int (*set_rts)(void *priv, int rts); - int (*get_rts)(void *priv, int *rts); - int (*set_frag)(void *priv, int frag); - int (*get_frag)(void *priv, int *frag); - int (*set_retry)(void *priv, int short_retry, int long_retry); - int (*get_retry)(void *priv, int *short_retry, int *long_retry); - - int (*sta_set_flags)(void *priv, const u8 *addr, - int flags_or, int flags_and); - int (*set_rate_sets)(void *priv, int *supp_rates, int *basic_rates, - int mode); - int (*set_channel_flag)(void *priv, int mode, int chan, int flag, - unsigned char power_level, - unsigned char antenna_max); - int (*set_regulatory_domain)(void *priv, unsigned int rd); - int (*set_country)(void *priv, const char *country); - int (*set_ieee80211d)(void *priv, int enabled); - int (*set_beacon)(const char *ifname, void *priv, - u8 *head, size_t head_len, - u8 *tail, size_t tail_len); - - /* Configure internal bridge: - * 0 = disabled, i.e., client separation is enabled (no bridging of - * packets between associated STAs - * 1 = enabled, i.e., bridge packets between associated STAs (default) - */ - int (*set_internal_bridge)(void *priv, int value); - int (*set_beacon_int)(void *priv, int value); - int (*set_dtim_period)(const char *ifname, void *priv, int value); - /* Configure broadcast SSID mode: - * 0 = include SSID in Beacon frames and reply to Probe Request frames - * that use broadcast SSID - * 1 = hide SSID from Beacon frames and ignore Probe Request frames for - * broadcast SSID - */ - int (*set_broadcast_ssid)(void *priv, int value); - int (*set_cts_protect)(void *priv, int value); - int (*set_key_tx_rx_threshold)(void *priv, int value); - int (*set_preamble)(void *priv, int value); - int (*set_short_slot_time)(void *priv, int value); - int (*set_tx_queue_params)(void *priv, int queue, int aifs, int cw_min, - int cw_max, int burst_time); - int (*bss_add)(void *priv, const char *ifname, const u8 *bssid); - int (*bss_remove)(void *priv, const char *ifname); - int (*valid_bss_mask)(void *priv, const u8 *addr, const u8 *mask); - int (*passive_scan)(void *priv, int now, int our_mode_only, - int interval, int _listen, int *channel, - int *last_rx); - struct hostapd_hw_modes * (*get_hw_feature_data)(void *priv, - u16 *num_modes, - u16 *flags); - int (*if_add)(const char *iface, void *priv, - enum hostapd_driver_if_type type, char *ifname, - const u8 *addr); - int (*if_update)(void *priv, enum hostapd_driver_if_type type, - char *ifname, const u8 *addr); - int (*if_remove)(void *priv, enum hostapd_driver_if_type type, - const char *ifname, const u8 *addr); - int (*set_sta_vlan)(void *priv, const u8 *addr, const char *ifname, - int vlan_id); - /** - * commit - Optional commit changes handler - * @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); - - int (*set_radius_acl_auth)(void *priv, const u8 *mac, int accepted, - u32 session_timeout); - int (*set_radius_acl_expire)(void *priv, const u8 *mac); -}; - -static inline int -hostapd_driver_init(struct hostapd_data *hapd) -{ - if (hapd->driver == NULL || hapd->driver->init == NULL) - return -1; - return hapd->driver->init(hapd); -} - -static inline void -hostapd_driver_deinit(struct hostapd_data *hapd) -{ - if (hapd->driver == NULL || hapd->driver->deinit == NULL) - return; - hapd->driver->deinit(hapd->driver); -} - -static inline int -hostapd_wireless_event_init(struct hostapd_data *hapd) -{ - if (hapd->driver == NULL || - hapd->driver->wireless_event_init == NULL) - return 0; - return hapd->driver->wireless_event_init(hapd->driver); -} - -static inline void -hostapd_wireless_event_deinit(struct hostapd_data *hapd) -{ - if (hapd->driver == NULL || - hapd->driver->wireless_event_deinit == NULL) - return; - hapd->driver->wireless_event_deinit(hapd->driver); -} - -static inline int -hostapd_set_ieee8021x(const char *ifname, struct hostapd_data *hapd, - int enabled) -{ - if (hapd->driver == NULL || hapd->driver->set_ieee8021x == NULL) - return 0; - return hapd->driver->set_ieee8021x(ifname, hapd->driver, enabled); -} - -static inline 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->conf->iface, hapd->driver, - enabled); -} - -static inline int -hostapd_set_encryption(const char *ifname, struct hostapd_data *hapd, - const char *alg, const u8 *addr, int idx, - u8 *key, size_t key_len, int txkey) -{ - if (hapd->driver == NULL || hapd->driver->set_encryption == NULL) - return 0; - return hapd->driver->set_encryption(ifname, hapd->driver, alg, addr, - idx, key, key_len, txkey); -} - -static inline 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->driver, addr, idx, seq); -} - -static inline int -hostapd_get_seqnum_igtk(const char *ifname, struct hostapd_data *hapd, - const u8 *addr, int idx, u8 *seq) -{ - if (hapd->driver == NULL || hapd->driver->get_seqnum_igtk == NULL) - return -1; - return hapd->driver->get_seqnum_igtk(ifname, hapd->driver, addr, idx, - seq); -} - -static inline int -hostapd_flush(struct hostapd_data *hapd) -{ - if (hapd->driver == NULL || hapd->driver->flush == NULL) - return 0; - return hapd->driver->flush(hapd->driver); -} - -static inline 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->conf->iface, hapd->driver, - elem, elem_len); -} - -static inline int -hostapd_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->driver, data, addr); -} - -static inline int -hostapd_send_eapol(struct hostapd_data *hapd, const u8 *addr, const u8 *data, - size_t data_len, int encrypt) -{ - if (hapd->driver == NULL || hapd->driver->send_eapol == NULL) - return 0; - return hapd->driver->send_eapol(hapd->driver, addr, data, data_len, - encrypt, hapd->own_addr); -} - -static inline int -hostapd_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->driver, addr, reason); -} - -static inline int -hostapd_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->driver, addr, reason); -} - -static inline int -hostapd_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->driver, addr); -} - -static inline int -hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len) -{ - if (hapd->driver == NULL || hapd->driver->get_ssid == NULL) - return 0; - return hapd->driver->get_ssid(hapd->conf->iface, hapd->driver, buf, - len); -} - -static inline int -hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len) -{ - if (hapd->driver == NULL || hapd->driver->set_ssid == NULL) - return 0; - return hapd->driver->set_ssid(hapd->conf->iface, hapd->driver, buf, - len); -} - -static inline int -hostapd_send_mgmt_frame(struct hostapd_data *hapd, const void *msg, size_t len, - int flags) -{ - if (hapd->driver == NULL || hapd->driver->send_mgmt_frame == NULL) - return 0; - return hapd->driver->send_mgmt_frame(hapd->driver, msg, len, flags); -} - -static inline int -hostapd_set_assoc_ap(struct hostapd_data *hapd, const u8 *addr) -{ - if (hapd->driver == NULL || hapd->driver->set_assoc_ap == NULL) - return 0; - return hapd->driver->set_assoc_ap(hapd->driver, addr); -} - -static inline int -hostapd_set_countermeasures(struct hostapd_data *hapd, int enabled) -{ - if (hapd->driver == NULL || hapd->driver->set_countermeasures == NULL) - return 0; - return hapd->driver->set_countermeasures(hapd->driver, enabled); -} - -static inline int -hostapd_sta_add(const char *ifname, struct hostapd_data *hapd, const u8 *addr, - u16 aid, u16 capability, u8 *supp_rates, size_t supp_rates_len, - int flags) -{ - if (hapd->driver == NULL || hapd->driver->sta_add == NULL) - return 0; - return hapd->driver->sta_add(ifname, hapd->driver, addr, aid, - capability, supp_rates, supp_rates_len, - flags); -} - -static inline int -hostapd_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->driver, addr); -} - -static inline int -hostapd_set_freq(struct hostapd_data *hapd, int mode, int freq) -{ - if (hapd->driver == NULL || hapd->driver->set_freq == NULL) - return 0; - return hapd->driver->set_freq(hapd->driver, mode, freq); -} - -static inline 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->driver, rts); -} - -static inline int -hostapd_get_rts(struct hostapd_data *hapd, int *rts) -{ - if (hapd->driver == NULL || hapd->driver->get_rts == NULL) - return 0; - return hapd->driver->get_rts(hapd->driver, rts); -} - -static inline 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->driver, frag); -} - -static inline int -hostapd_get_frag(struct hostapd_data *hapd, int *frag) -{ - if (hapd->driver == NULL || hapd->driver->get_frag == NULL) - return 0; - return hapd->driver->get_frag(hapd->driver, frag); -} - -static inline int -hostapd_set_retry(struct hostapd_data *hapd, int short_retry, int long_retry) -{ - if (hapd->driver == NULL || hapd->driver->set_retry == NULL) - return 0; - return hapd->driver->set_retry(hapd->driver, short_retry, long_retry); -} - -static inline int -hostapd_get_retry(struct hostapd_data *hapd, int *short_retry, int *long_retry) -{ - if (hapd->driver == NULL || hapd->driver->get_retry == NULL) - return 0; - return hapd->driver->get_retry(hapd->driver, short_retry, long_retry); -} - -static inline int -hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr, - 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->driver, addr, flags_or, - flags_and); -} - -static inline 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->driver, supp_rates, - basic_rates, mode); -} - -static inline int -hostapd_set_channel_flag(struct hostapd_data *hapd, int mode, int chan, - int flag, unsigned char power_level, - unsigned char antenna_max) -{ - if (hapd->driver == NULL || hapd->driver->set_channel_flag == NULL) - return 0; - return hapd->driver->set_channel_flag(hapd->driver, mode, chan, flag, - power_level, antenna_max); -} - -static inline int -hostapd_set_regulatory_domain(struct hostapd_data *hapd, unsigned int rd) -{ - if (hapd->driver == NULL || - hapd->driver->set_regulatory_domain == NULL) - return 0; - return hapd->driver->set_regulatory_domain(hapd->driver, rd); -} - -static inline 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->driver, country); -} - -static inline int -hostapd_set_ieee80211d(struct hostapd_data *hapd, int enabled) -{ - if (hapd->driver == NULL || - hapd->driver->set_ieee80211d == NULL) - return 0; - return hapd->driver->set_ieee80211d(hapd->driver, enabled); -} - -void driver_register(const char *name, const struct driver_ops *ops); -void driver_unregister(const char *name); -const struct driver_ops *driver_lookup(const char *name); - -static inline int -hostapd_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->driver, addr); -} - -static inline int -hostapd_set_beacon(const char *ifname, struct hostapd_data *hapd, - u8 *head, size_t head_len, - u8 *tail, size_t tail_len) -{ - if (hapd->driver == NULL || hapd->driver->set_beacon == NULL) - return 0; - return hapd->driver->set_beacon(ifname, hapd->driver, head, head_len, - tail, tail_len); -} - -static inline int -hostapd_set_internal_bridge(struct hostapd_data *hapd, int value) -{ - if (hapd->driver == NULL || hapd->driver->set_internal_bridge == NULL) - return 0; - return hapd->driver->set_internal_bridge(hapd->driver, value); -} - -static inline int -hostapd_set_beacon_int(struct hostapd_data *hapd, int value) -{ - if (hapd->driver == NULL || hapd->driver->set_beacon_int == NULL) - return 0; - return hapd->driver->set_beacon_int(hapd->driver, value); -} - -static inline int -hostapd_set_dtim_period(struct hostapd_data *hapd, int value) -{ - if (hapd->driver == NULL || hapd->driver->set_dtim_period == NULL) - return 0; - return hapd->driver->set_dtim_period(hapd->conf->iface, hapd->driver, - value); -} - -static inline int -hostapd_set_broadcast_ssid(struct hostapd_data *hapd, int value) -{ - if (hapd->driver == NULL || hapd->driver->set_broadcast_ssid == NULL) - return 0; - return hapd->driver->set_broadcast_ssid(hapd->driver, value); -} - -static inline 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->driver, value); -} - -static inline int -hostapd_set_key_tx_rx_threshold(struct hostapd_data *hapd, int value) -{ - if (hapd->driver == NULL || - hapd->driver->set_key_tx_rx_threshold == NULL) - return 0; - return hapd->driver->set_key_tx_rx_threshold(hapd->driver, value); -} - -static inline 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->driver, value); -} - -static inline 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->driver, value); -} - -static inline 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->driver, queue, aifs, - cw_min, cw_max, burst_time); -} - -static inline int -hostapd_bss_add(struct hostapd_data *hapd, const char *ifname, const u8 *bssid) -{ - if (hapd->driver == NULL || hapd->driver->bss_add == NULL) - return 0; - return hapd->driver->bss_add(hapd->driver, ifname, bssid); -} - -static inline int -hostapd_bss_remove(struct hostapd_data *hapd, const char *ifname) -{ - if (hapd->driver == NULL || hapd->driver->bss_remove == NULL) - return 0; - return hapd->driver->bss_remove(hapd->driver, ifname); -} - -static inline 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->driver, addr, mask); -} - -static inline int -hostapd_if_add(struct hostapd_data *hapd, enum hostapd_driver_if_type type, - char *ifname, const u8 *addr) -{ - if (hapd->driver == NULL || hapd->driver->if_add == NULL) - return -1; - return hapd->driver->if_add(hapd->conf->iface, hapd->driver, type, - ifname, addr); -} - -static inline int -hostapd_if_update(struct hostapd_data *hapd, enum hostapd_driver_if_type type, - char *ifname, const u8 *addr) -{ - if (hapd->driver == NULL || hapd->driver->if_update == NULL) - return -1; - return hapd->driver->if_update(hapd->driver, type, ifname, addr); -} - -static inline int -hostapd_if_remove(struct hostapd_data *hapd, enum hostapd_driver_if_type type, - char *ifname, const u8 *addr) -{ - if (hapd->driver == NULL || hapd->driver->if_remove == NULL) - return -1; - return hapd->driver->if_remove(hapd->driver, type, ifname, addr); -} - -static inline int -hostapd_passive_scan(struct hostapd_data *hapd, int now, int our_mode_only, - int interval, int _listen, int *channel, - int *last_rx) -{ - if (hapd->driver == NULL || hapd->driver->passive_scan == NULL) - return -1; - return hapd->driver->passive_scan(hapd->driver, now, our_mode_only, - interval, _listen, channel, last_rx); -} - -static inline 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->driver, num_modes, - flags); -} - -static inline int -hostapd_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->driver, addr, ifname, vlan_id); -} - -static inline int -hostapd_driver_commit(struct hostapd_data *hapd) -{ - if (hapd->driver == NULL || hapd->driver->commit == NULL) - return 0; - return hapd->driver->commit(hapd->driver); -} - -static inline int -hostapd_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->driver, mac, accepted, - session_timeout); -} - -static inline int -hostapd_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->driver, mac); -} - -#endif /* DRIVER_H */ diff --git a/contrib/hostapd/driver_test.c b/contrib/hostapd/driver_test.c deleted file mode 100644 index 368d76b06103..000000000000 --- a/contrib/hostapd/driver_test.c +++ /dev/null @@ -1,1057 +0,0 @@ -/* - * hostapd / Driver interface for development testing - * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 <sys/ioctl.h> -#include <sys/un.h> -#include <dirent.h> - -#include "hostapd.h" -#include "driver.h" -#include "sha1.h" -#include "eloop.h" -#include "ieee802_1x.h" -#include "sta_info.h" -#include "eapol_sm.h" -#include "wpa.h" -#include "accounting.h" -#include "radius.h" -#include "l2_packet.h" -#include "ieee802_11.h" -#include "hw_features.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 test_driver_bss *next; - char ifname[IFNAMSIZ + 1]; - u8 bssid[ETH_ALEN]; - u8 *ie; - size_t ielen; - u8 ssid[32]; - size_t ssid_len; - int privacy; -}; - -struct test_driver_data { - struct driver_ops ops; - struct hostapd_data *hapd; - struct test_client_socket *cli; - int test_socket; - struct test_driver_bss *bss; - char *socket_dir; - char *own_socket_path; -}; - -static const struct driver_ops test_driver_ops; - - -static void test_driver_free_bss(struct test_driver_bss *bss) -{ - free(bss->ie); - free(bss); -} - - -static void test_driver_free_priv(struct test_driver_data *drv) -{ - struct test_driver_bss *bss, *prev; - - if (drv == NULL) - return; - - bss = drv->bss; - while (bss) { - prev = bss; - bss = bss->next; - test_driver_free_bss(prev); - } - free(drv->own_socket_path); - free(drv->socket_dir); - free(drv); -} - - -static struct test_client_socket * -test_driver_get_cli(struct test_driver_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) -{ - struct test_driver_data *drv = priv; - 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 = htons(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_mgmt_frame(void *priv, const void *buf, - size_t len, int flags) -{ - struct test_driver_data *drv = priv; - struct msghdr msg; - struct iovec io[2]; - const u8 *dest; - int ret = 0, broadcast = 0; - char desttxt[30]; - struct sockaddr_un addr; - struct dirent *dent; - DIR *dir; - struct ieee80211_hdr *hdr; - u16 fc; - - if (drv->test_socket < 0 || len < 10 || drv->socket_dir == NULL) { - wpa_printf(MSG_DEBUG, "%s: invalid parameters (sock=%d len=%lu" - " socket_dir=%p)", - __func__, drv->test_socket, (unsigned long) len, - drv->socket_dir); - return -1; - } - - dest = buf; - dest += 4; - broadcast = memcmp(dest, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0; - snprintf(desttxt, sizeof(desttxt), MACSTR, MAC2STR(dest)); - - io[0].iov_base = "MLME "; - io[0].iov_len = 5; - io[1].iov_base = (void *) buf; - io[1].iov_len = len; - - memset(&msg, 0, sizeof(msg)); - msg.msg_iov = io; - msg.msg_iovlen = 2; - - dir = opendir(drv->socket_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->socket_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 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"); - } - closedir(dir); - - hdr = (struct ieee80211_hdr *) buf; - fc = le_to_host16(hdr->frame_control); - ieee802_11_mgmt_cb(drv->hapd, (u8 *) buf, len, WLAN_FC_GET_STYPE(fc), - ret >= 0); - - return ret; -} - - -static void test_driver_scan(struct test_driver_data *drv, - struct sockaddr_un *from, socklen_t fromlen) -{ - char buf[512], *pos, *end; - int ret; - struct test_driver_bss *bss; - - wpa_printf(MSG_DEBUG, "test_driver: SCAN"); - - for (bss = drv->bss; bss; bss = bss->next) { - 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); - - 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 struct hostapd_data * test_driver_get_hapd(struct test_driver_data *drv, - struct test_driver_bss *bss) -{ - struct hostapd_iface *iface = drv->hapd->iface; - struct hostapd_data *hapd = NULL; - size_t i; - - if (bss == NULL) { - wpa_printf(MSG_DEBUG, "%s: bss == NULL", __func__); - return NULL; - } - - for (i = 0; i < iface->num_bss; i++) { - hapd = iface->bss[i]; - if (memcmp(hapd->own_addr, bss->bssid, ETH_ALEN) == 0) - break; - } - if (i == iface->num_bss) { - wpa_printf(MSG_DEBUG, "%s: no matching interface entry found " - "for BSSID " MACSTR, __func__, MAC2STR(bss->bssid)); - return NULL; - } - - return hapd; -} - - -static int test_driver_new_sta(struct test_driver_data *drv, - struct test_driver_bss *bss, const u8 *addr, - const u8 *ie, size_t ielen) -{ - struct hostapd_data *hapd; - struct sta_info *sta; - int new_assoc, res; - - hapd = test_driver_get_hapd(drv, bss); - if (hapd == NULL) - return -1; - - 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) - return -1; - } - accounting_sta_get_id(hapd, sta); - - if (hapd->conf->wpa) { - if (ie == NULL || ielen == 0) { - printf("test_driver: no IE from STA\n"); - return -1; - } - if (sta->wpa_sm == NULL) - sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, - sta->addr); - if (sta->wpa_sm == NULL) { - printf("test_driver: Failed to initialize WPA state " - "machine\n"); - return -1; - } - res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, - ie, ielen); - if (res != WPA_IE_OK) { - printf("WPA/RSN information element rejected? " - "(res %u)\n", res); - return -1; - } - } - - 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 void test_driver_assoc(struct test_driver_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; - - /* data: STA-addr SSID(hex) IEs(hex) */ - - cli = wpa_zalloc(sizeof(*cli)); - if (cli == NULL) - return; - - if (hwaddr_aton(data, cli->addr)) { - printf("test_socket: Invalid MAC address '%s' in ASSOC\n", - data); - 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__); - 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; - } - - for (bss = drv->bss; bss; bss = bss->next) { - if (bss->ssid_len == ssid_len && - memcmp(bss->ssid, ssid, ssid_len) == 0) - break; - } - if (bss == NULL) { - wpa_printf(MSG_DEBUG, "%s: No matching SSID found from " - "configured BSSes", __func__); - 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); - - if (test_driver_new_sta(drv, bss, cli->addr, ie, ielen) < 0) { - wpa_printf(MSG_DEBUG, "test_driver: failed to add new STA"); - } -} - - -static void test_driver_disassoc(struct test_driver_data *drv, - struct sockaddr_un *from, socklen_t fromlen) -{ - struct test_client_socket *cli; - struct sta_info *sta; - - cli = test_driver_get_cli(drv, from, fromlen); - if (!cli) - return; - - hostapd_logger(drv->hapd, cli->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "disassociated"); - - sta = ap_get_sta(drv->hapd, cli->addr); - if (sta != NULL) { - sta->flags &= ~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(drv->hapd, sta); - } -} - - -static void test_driver_eapol(struct test_driver_data *drv, - struct sockaddr_un *from, socklen_t fromlen, - u8 *data, size_t datalen) -{ - struct test_client_socket *cli; - if (datalen > 14) { - u8 *proto = data + 2 * ETH_ALEN; - /* Skip Ethernet header */ - wpa_printf(MSG_DEBUG, "test_driver: dst=" MACSTR " src=" - MACSTR " proto=%04x", - MAC2STR(data), MAC2STR(data + ETH_ALEN), - (proto[0] << 8) | proto[1]); - data += 14; - datalen -= 14; - } - cli = test_driver_get_cli(drv, from, fromlen); - if (cli) { - struct hostapd_data *hapd; - hapd = test_driver_get_hapd(drv, cli->bss); - if (hapd == NULL) - return; - ieee802_1x_receive(hapd, cli->addr, data, datalen); - } else { - wpa_printf(MSG_DEBUG, "test_socket: EAPOL from unknown " - "client"); - } -} - - -static void test_driver_mlme(struct test_driver_data *drv, - struct sockaddr_un *from, socklen_t fromlen, - u8 *data, size_t datalen) -{ - struct ieee80211_hdr *hdr; - u16 fc; - - hdr = (struct ieee80211_hdr *) data; - - if (test_driver_get_cli(drv, from, fromlen) == NULL && datalen >= 16) { - struct test_client_socket *cli; - cli = wpa_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; - } - ieee802_11_mgmt(drv->hapd, data, datalen, WLAN_FC_GET_STYPE(fc), NULL); -} - - -static void test_driver_receive_unix(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct test_driver_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 (strcmp(buf, "SCAN") == 0) { - test_driver_scan(drv, &from, fromlen); - } 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, "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(const char *ifname, void *priv, - const u8 *elem, size_t elem_len) -{ - struct test_driver_data *drv = priv; - struct test_driver_bss *bss; - - for (bss = drv->bss; bss; bss = bss->next) { - if (strcmp(bss->ifname, ifname) != 0) - continue; - - free(bss->ie); - - if (elem == NULL) { - bss->ie = NULL; - bss->ielen = 0; - return 0; - } - - bss->ie = malloc(elem_len); - if (bss->ie) { - memcpy(bss->ie, elem, elem_len); - bss->ielen = elem_len; - return 0; - } else { - bss->ielen = 0; - return -1; - } - } - - return -1; -} - - -static int test_driver_sta_deauth(void *priv, const u8 *addr, int reason) -{ - struct test_driver_data *drv = priv; - 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 *addr, int reason) -{ - struct test_driver_data *drv = priv; - 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 struct hostapd_hw_modes * -test_driver_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags) -{ - struct hostapd_hw_modes *modes; - - *num_modes = 3; - *flags = 0; - modes = wpa_zalloc(*num_modes * sizeof(struct hostapd_hw_modes)); - if (modes == NULL) - return NULL; - modes[0].mode = HOSTAPD_MODE_IEEE80211G; - modes[0].num_channels = 1; - modes[0].num_rates = 1; - modes[0].channels = wpa_zalloc(sizeof(struct hostapd_channel_data)); - modes[0].rates = wpa_zalloc(sizeof(struct hostapd_rate_data)); - if (modes[0].channels == NULL || modes[0].rates == NULL) { - hostapd_free_hw_features(modes, *num_modes); - return NULL; - } - modes[0].channels[0].chan = 1; - modes[0].channels[0].freq = 2412; - modes[0].channels[0].flag = HOSTAPD_CHAN_W_SCAN | - HOSTAPD_CHAN_W_ACTIVE_SCAN; - modes[0].rates[0].rate = 10; - modes[0].rates[0].flags = HOSTAPD_RATE_BASIC | HOSTAPD_RATE_SUPPORTED | - HOSTAPD_RATE_CCK | HOSTAPD_RATE_MANDATORY; - - modes[1].mode = HOSTAPD_MODE_IEEE80211B; - modes[1].num_channels = 1; - modes[1].num_rates = 1; - modes[1].channels = wpa_zalloc(sizeof(struct hostapd_channel_data)); - modes[1].rates = wpa_zalloc(sizeof(struct hostapd_rate_data)); - if (modes[1].channels == NULL || modes[1].rates == NULL) { - hostapd_free_hw_features(modes, *num_modes); - return NULL; - } - modes[1].channels[0].chan = 1; - modes[1].channels[0].freq = 2412; - modes[1].channels[0].flag = HOSTAPD_CHAN_W_SCAN | - HOSTAPD_CHAN_W_ACTIVE_SCAN; - modes[1].rates[0].rate = 10; - modes[1].rates[0].flags = HOSTAPD_RATE_BASIC | HOSTAPD_RATE_SUPPORTED | - HOSTAPD_RATE_CCK | HOSTAPD_RATE_MANDATORY; - - modes[2].mode = HOSTAPD_MODE_IEEE80211A; - modes[2].num_channels = 1; - modes[2].num_rates = 1; - modes[2].channels = wpa_zalloc(sizeof(struct hostapd_channel_data)); - modes[2].rates = wpa_zalloc(sizeof(struct hostapd_rate_data)); - if (modes[2].channels == NULL || modes[2].rates == NULL) { - hostapd_free_hw_features(modes, *num_modes); - return NULL; - } - modes[2].channels[0].chan = 60; - modes[2].channels[0].freq = 5300; - modes[2].channels[0].flag = HOSTAPD_CHAN_W_SCAN | - HOSTAPD_CHAN_W_ACTIVE_SCAN; - modes[2].rates[0].rate = 60; - modes[2].rates[0].flags = HOSTAPD_RATE_BASIC | HOSTAPD_RATE_SUPPORTED | - HOSTAPD_RATE_MANDATORY; - - return modes; -} - - -static int test_driver_bss_add(void *priv, const char *ifname, const u8 *bssid) -{ - struct test_driver_data *drv = priv; - struct test_driver_bss *bss; - - wpa_printf(MSG_DEBUG, "%s(ifname=%s bssid=" MACSTR ")", - __func__, ifname, MAC2STR(bssid)); - - bss = wpa_zalloc(sizeof(*bss)); - if (bss == NULL) - return -1; - - strncpy(bss->ifname, ifname, IFNAMSIZ); - memcpy(bss->bssid, bssid, ETH_ALEN); - - bss->next = drv->bss; - drv->bss = bss; - - return 0; -} - - -static int test_driver_bss_remove(void *priv, const char *ifname) -{ - struct test_driver_data *drv = priv; - struct test_driver_bss *bss, *prev; - struct test_client_socket *cli, *prev_c; - - wpa_printf(MSG_DEBUG, "%s(ifname=%s)", __func__, ifname); - - for (prev = NULL, bss = drv->bss; bss; prev = bss, bss = bss->next) { - if (strcmp(bss->ifname, ifname) != 0) - continue; - - if (prev) - prev->next = bss->next; - else - drv->bss = bss->next; - - 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; - free(cli); - break; - } - - test_driver_free_bss(bss); - return 0; - } - - return -1; -} - - -static int test_driver_if_add(const char *iface, void *priv, - enum hostapd_driver_if_type type, char *ifname, - const u8 *addr) -{ - wpa_printf(MSG_DEBUG, "%s(iface=%s type=%d ifname=%s)", - __func__, iface, type, ifname); - return 0; -} - - -static int test_driver_if_update(void *priv, enum hostapd_driver_if_type type, - char *ifname, const u8 *addr) -{ - wpa_printf(MSG_DEBUG, "%s(type=%d ifname=%s)", __func__, type, ifname); - return 0; -} - - -static int test_driver_if_remove(void *priv, enum hostapd_driver_if_type type, - const char *ifname, const u8 *addr) -{ - wpa_printf(MSG_DEBUG, "%s(type=%d ifname=%s)", __func__, type, 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(const char *ifname, void *priv, const u8 *buf, - int len) -{ - struct test_driver_data *drv = priv; - struct test_driver_bss *bss; - - wpa_printf(MSG_DEBUG, "%s(ifname=%s)", __func__, ifname); - wpa_hexdump_ascii(MSG_DEBUG, "test_driver_set_ssid: SSID", buf, len); - - for (bss = drv->bss; bss; bss = bss->next) { - if (strcmp(bss->ifname, ifname) != 0) - continue; - - if (len < 0 || (size_t) len > sizeof(bss->ssid)) - return -1; - - memcpy(bss->ssid, buf, len); - bss->ssid_len = len; - - return 0; - } - - return -1; -} - - -static int test_driver_set_privacy(const char *ifname, void *priv, int enabled) -{ - struct test_driver_data *drv = priv; - struct test_driver_bss *bss; - - wpa_printf(MSG_DEBUG, "%s(ifname=%s enabled=%d)", - __func__, ifname, enabled); - - for (bss = drv->bss; bss; bss = bss->next) { - if (strcmp(bss->ifname, ifname) != 0) - continue; - - bss->privacy = enabled; - - return 0; - } - - return -1; -} - - -static int test_driver_set_encryption(const char *iface, void *priv, - const char *alg, const u8 *addr, int idx, - const u8 *key, size_t key_len, int txkey) -{ - wpa_printf(MSG_DEBUG, "%s(iface=%s alg=%s idx=%d txkey=%d)", - __func__, iface, alg, idx, txkey); - if (addr) - wpa_printf(MSG_DEBUG, " addr=" MACSTR, MAC2STR(addr)); - if (key) - wpa_hexdump_key(MSG_DEBUG, " key", key, key_len); - 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(const char *ifname, void *priv, const u8 *addr, - u16 aid, u16 capability, u8 *supp_rates, - size_t supp_rates_len, int flags) -{ - struct test_driver_data *drv = priv; - struct test_client_socket *cli; - struct test_driver_bss *bss; - - wpa_printf(MSG_DEBUG, "%s(ifname=%s addr=" MACSTR " aid=%d " - "capability=0x%x flags=0x%x", - __func__, ifname, MAC2STR(addr), aid, capability, flags); - wpa_hexdump(MSG_DEBUG, "test_driver_sta_add - supp_rates", - supp_rates, supp_rates_len); - - 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 matching client entry", - __func__); - return -1; - } - - for (bss = drv->bss; bss; bss = bss->next) { - if (strcmp(ifname, bss->ifname) == 0) - break; - } - if (bss == NULL) { - wpa_printf(MSG_DEBUG, "%s: No matching interface found from " - "configured BSSes", __func__); - return -1; - } - - cli->bss = bss; - - return 0; -} - - -static int test_driver_init(struct hostapd_data *hapd) -{ - struct test_driver_data *drv; - struct sockaddr_un addr; - - drv = wpa_zalloc(sizeof(struct test_driver_data)); - if (drv == NULL) { - printf("Could not allocate memory for test driver data\n"); - return -1; - } - drv->bss = wpa_zalloc(sizeof(*drv->bss)); - if (drv->bss == NULL) { - printf("Could not allocate memory for test driver BSS data\n"); - free(drv); - return -1; - } - - drv->ops = test_driver_ops; - drv->hapd = hapd; - - /* Generate a MAC address to help testing with multiple APs */ - hapd->own_addr[0] = 0x02; /* locally administered */ - sha1_prf((const u8 *) hapd->conf->iface, strlen(hapd->conf->iface), - "hostapd test bssid generation", - (const u8 *) hapd->conf->ssid.ssid, hapd->conf->ssid.ssid_len, - hapd->own_addr + 1, ETH_ALEN - 1); - - strncpy(drv->bss->ifname, hapd->conf->iface, IFNAMSIZ); - memcpy(drv->bss->bssid, hapd->own_addr, ETH_ALEN); - - if (hapd->conf->test_socket) { - if (strlen(hapd->conf->test_socket) >= sizeof(addr.sun_path)) { - printf("Too long test_socket path\n"); - test_driver_free_priv(drv); - return -1; - } - if (strncmp(hapd->conf->test_socket, "DIR:", 4) == 0) { - size_t len = strlen(hapd->conf->test_socket) + 30; - drv->socket_dir = strdup(hapd->conf->test_socket + 4); - drv->own_socket_path = malloc(len); - if (drv->own_socket_path) { - snprintf(drv->own_socket_path, len, - "%s/AP-" MACSTR, - hapd->conf->test_socket + 4, - MAC2STR(hapd->own_addr)); - } - } else { - drv->own_socket_path = strdup(hapd->conf->test_socket); - } - if (drv->own_socket_path == NULL) { - test_driver_free_priv(drv); - return -1; - } - - drv->test_socket = socket(PF_UNIX, SOCK_DGRAM, 0); - if (drv->test_socket < 0) { - perror("socket(PF_UNIX)"); - test_driver_free_priv(drv); - return -1; - } - - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - strncpy(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); - test_driver_free_priv(drv); - return -1; - } - eloop_register_read_sock(drv->test_socket, - test_driver_receive_unix, drv, NULL); - } else - drv->test_socket = -1; - - hapd->driver = &drv->ops; - return 0; -} - - -static void test_driver_deinit(void *priv) -{ - struct test_driver_data *drv = priv; - struct test_client_socket *cli, *prev; - - cli = drv->cli; - while (cli) { - prev = cli; - cli = cli->next; - free(prev); - } - - if (drv->test_socket >= 0) { - eloop_unregister_read_sock(drv->test_socket); - close(drv->test_socket); - unlink(drv->own_socket_path); - } - - drv->hapd->driver = NULL; - - /* There should be only one BSS remaining at this point. */ - if (drv->bss == NULL) - wpa_printf(MSG_ERROR, "%s: drv->bss == NULL", __func__); - else if (drv->bss->next) - wpa_printf(MSG_ERROR, "%s: drv->bss->next != NULL", __func__); - - test_driver_free_priv(drv); -} - - -static const struct driver_ops test_driver_ops = { - .name = "test", - .init = test_driver_init, - .deinit = test_driver_deinit, - .send_eapol = test_driver_send_eapol, - .send_mgmt_frame = test_driver_send_mgmt_frame, - .set_generic_elem = test_driver_set_generic_elem, - .sta_deauth = test_driver_sta_deauth, - .sta_disassoc = test_driver_sta_disassoc, - .get_hw_feature_data = test_driver_get_hw_feature_data, - .bss_add = test_driver_bss_add, - .bss_remove = test_driver_bss_remove, - .if_add = test_driver_if_add, - .if_update = test_driver_if_update, - .if_remove = test_driver_if_remove, - .valid_bss_mask = test_driver_valid_bss_mask, - .set_ssid = test_driver_set_ssid, - .set_privacy = test_driver_set_privacy, - .set_encryption = test_driver_set_encryption, - .set_sta_vlan = test_driver_set_sta_vlan, - .sta_add = test_driver_sta_add, -}; - - -void test_driver_register(void) -{ - driver_register(test_driver_ops.name, &test_driver_ops); -} diff --git a/contrib/hostapd/eap.c b/contrib/hostapd/eap.c deleted file mode 100644 index 3f623cab4b05..000000000000 --- a/contrib/hostapd/eap.c +++ /dev/null @@ -1,1140 +0,0 @@ -/* - * hostapd / EAP Standalone Authenticator state machine (RFC 4137) - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * $FreeBSD$ - */ - -#include "includes.h" - -#include "hostapd.h" -#include "sta_info.h" -#include "eap_i.h" -#include "state_machine.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, u8 *resp, size_t len); -static u8 * eap_sm_buildSuccess(struct eap_sm *sm, int id, size_t *len); -static u8 * eap_sm_buildFailure(struct eap_sm *sm, int id, size_t *len); -static int eap_sm_nextId(struct eap_sm *sm, int id); -static void eap_sm_Policy_update(struct eap_sm *sm, 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 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 void eapol_set_eapReqData(struct eap_sm *sm, - const u8 *eapReqData, size_t eapReqDataLen) -{ - wpa_hexdump(MSG_MSGDUMP, "EAP: eapReqData -> EAPOL", - sm->eapReqData, sm->eapReqDataLen); - sm->eapol_cb->set_eapReqData(sm->eapol_ctx, eapReqData, eapReqDataLen); -} - - -static void eapol_set_eapKeyData(struct eap_sm *sm, - const u8 *eapKeyData, size_t eapKeyDataLen) -{ - wpa_hexdump(MSG_MSGDUMP, "EAP: eapKeyData -> EAPOL", - sm->eapKeyData, sm->eapKeyDataLen); - sm->eapol_cb->set_eapKeyData(sm->eapol_ctx, eapKeyData, eapKeyDataLen); -} - - -/** - * eap_user_get - Fetch user information from the database - * @sm: Pointer to EAP state machine allocated with eap_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 = wpa_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; - eapol_set_bool(sm, EAPOL_eapSuccess, FALSE); - eapol_set_bool(sm, EAPOL_eapFail, FALSE); - eapol_set_bool(sm, EAPOL_eapTimeout, FALSE); - free(sm->eapKeyData); - sm->eapKeyData = NULL; - sm->eapKeyDataLen = 0; - /* eapKeyAvailable = FALSE */ - eapol_set_bool(sm, EAPOL_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->eapRespData, sm->eapRespDataLen); - if (sm->rxResp) { - sm->currentId = sm->respId; - } - } - sm->num_rounds = 0; - sm->method_pending = METHOD_PENDING_NONE; -} - - -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_sm_get_eap_methods(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; - } - } -} - - -SM_STATE(EAP, IDLE) -{ - SM_ENTRY(EAP, IDLE); - - sm->retransWhile = eap_sm_calculateTimeout(sm, sm->retransCount, - sm->eapSRTT, sm->eapRTTVAR, - sm->methodTimeout); -} - - -SM_STATE(EAP, RETRANSMIT) -{ - SM_ENTRY(EAP, RETRANSMIT); - - /* TODO: Is this needed since EAPOL state machines take care of - * retransmit? */ -} - - -SM_STATE(EAP, RECEIVED) -{ - SM_ENTRY(EAP, RECEIVED); - - /* parse rxResp, respId, respMethod */ - eap_sm_parseEapResp(sm, sm->eapRespData, sm->eapRespDataLen); - sm->num_rounds++; -} - - -SM_STATE(EAP, DISCARD) -{ - SM_ENTRY(EAP, DISCARD); - eapol_set_bool(sm, EAPOL_eapResp, FALSE); - eapol_set_bool(sm, EAPOL_eapNoReq, TRUE); -} - - -SM_STATE(EAP, SEND_REQUEST) -{ - SM_ENTRY(EAP, SEND_REQUEST); - - sm->retransCount = 0; - if (sm->eapReqData) { - eapol_set_eapReqData(sm, sm->eapReqData, sm->eapReqDataLen); - free(sm->lastReqData); - sm->lastReqData = sm->eapReqData; - sm->lastReqDataLen = sm->eapReqDataLen; - sm->eapReqData = NULL; - sm->eapReqDataLen = 0; - eapol_set_bool(sm, EAPOL_eapResp, FALSE); - eapol_set_bool(sm, EAPOL_eapReq, TRUE); - } else { - wpa_printf(MSG_INFO, "EAP: SEND_REQUEST - no eapReqData"); - eapol_set_bool(sm, EAPOL_eapResp, FALSE); - eapol_set_bool(sm, EAPOL_eapReq, FALSE); - eapol_set_bool(sm, EAPOL_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->eapRespData, sm->eapRespDataLen); - } -} - - -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; - free(sm->eapReqData); - sm->eapReqData = sm->m->buildReq(sm, sm->eap_method_priv, - sm->currentId, &sm->eapReqDataLen); - 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->eapRespData, - sm->eapRespDataLen); - if (sm->m->isDone(sm, sm->eap_method_priv)) { - eap_sm_Policy_update(sm, NULL, 0); - free(sm->eapKeyData); - if (sm->m->getKey) { - sm->eapKeyData = sm->m->getKey(sm, sm->eap_method_priv, - &sm->eapKeyDataLen); - } else { - sm->eapKeyData = NULL; - sm->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_sm_get_eap_methods(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; -} - - -SM_STATE(EAP, NAK) -{ - struct eap_hdr *nak; - size_t len = 0; - u8 *pos, *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 = (struct eap_hdr *) sm->eapRespData; - if (nak && sm->eapRespDataLen > sizeof(*nak)) { - len = ntohs(nak->length); - if (len > sm->eapRespDataLen) - len = sm->eapRespDataLen; - pos = (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); - - eapol_set_bool(sm, EAPOL_eapTimeout, TRUE); -} - - -SM_STATE(EAP, FAILURE) -{ - SM_ENTRY(EAP, FAILURE); - - free(sm->eapReqData); - sm->eapReqData = eap_sm_buildFailure(sm, sm->currentId, - &sm->eapReqDataLen); - if (sm->eapReqData) { - eapol_set_eapReqData(sm, sm->eapReqData, sm->eapReqDataLen); - free(sm->eapReqData); - sm->eapReqData = NULL; - sm->eapReqDataLen = 0; - } - free(sm->lastReqData); - sm->lastReqData = NULL; - sm->lastReqDataLen = 0; - eapol_set_bool(sm, EAPOL_eapFail, TRUE); -} - - -SM_STATE(EAP, SUCCESS) -{ - SM_ENTRY(EAP, SUCCESS); - - free(sm->eapReqData); - sm->eapReqData = eap_sm_buildSuccess(sm, sm->currentId, - &sm->eapReqDataLen); - if (sm->eapReqData) { - eapol_set_eapReqData(sm, sm->eapReqData, sm->eapReqDataLen); - free(sm->eapReqData); - sm->eapReqData = NULL; - sm->eapReqDataLen = 0; - } - free(sm->lastReqData); - sm->lastReqData = NULL; - sm->lastReqDataLen = 0; - if (sm->eapKeyData) { - eapol_set_eapKeyData(sm, sm->eapKeyData, sm->eapKeyDataLen); - } - eapol_set_bool(sm, EAPOL_eapSuccess, TRUE); -} - - -SM_STEP(EAP) -{ - 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_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 (eapol_get_bool(sm, EAPOL_portEnabled)) - SM_ENTER(EAP, INITIALIZE); - break; - case EAP_IDLE: - if (sm->retransWhile == 0) - SM_ENTER(EAP, RETRANSMIT); - else if (eapol_get_bool(sm, EAPOL_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 - SM_ENTER(EAP, PROPOSE_METHOD); - break; - case EAP_TIMEOUT_FAILURE: - break; - case EAP_FAILURE: - break; - case EAP_SUCCESS: - break; - } -} - - -static int eap_sm_calculateTimeout(struct eap_sm *sm, int retransCount, - int eapSRTT, int eapRTTVAR, - int methodTimeout) -{ - /* For now, retransmission is done in EAPOL state machines, so make - * sure EAP state machine does not end up trying to retransmit packets. - */ - return 1; -} - - -static void eap_sm_parseEapResp(struct eap_sm *sm, u8 *resp, size_t len) -{ - 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 || len < sizeof(*hdr)) - return; - - hdr = (struct eap_hdr *) resp; - plen = ntohs(hdr->length); - if (plen > len) { - wpa_printf(MSG_DEBUG, "EAP: Ignored truncated EAP-Packet " - "(len=%lu plen=%lu)", (unsigned long) len, - (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 u8 * eap_sm_buildSuccess(struct eap_sm *sm, int id, size_t *len) -{ - struct eap_hdr *resp; - wpa_printf(MSG_DEBUG, "EAP: Building EAP-Success (id=%d)", id); - - *len = sizeof(*resp); - resp = malloc(*len); - if (resp == NULL) - return NULL; - resp->code = EAP_CODE_SUCCESS; - resp->identifier = id; - resp->length = htons(*len); - - return (u8 *) resp; -} - - -static u8 * eap_sm_buildFailure(struct eap_sm *sm, int id, size_t *len) -{ - struct eap_hdr *resp; - wpa_printf(MSG_DEBUG, "EAP: Building EAP-Failure (id=%d)", id); - - *len = sizeof(*resp); - resp = malloc(*len); - if (resp == NULL) - return NULL; - resp->code = EAP_CODE_FAILURE; - resp->identifier = id; - resp->length = htons(*len); - - return (u8 *) resp; -} - - -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_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, 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 */ - 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, 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->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) { - 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; - } - sm->update_user = 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_sm_step - Step EAP state machine - * @sm: Pointer to EAP state machine allocated with eap_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_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_set_eapRespData - Set EAP response (eapRespData) - * @sm: Pointer to EAP state machine allocated with eap_sm_init() - * @eapRespData: EAP-Response payload from the supplicant - * @eapRespDataLen: Length of eapRespData in bytes - * - * This function is called when an EAP-Response is received from a supplicant. - */ -void eap_set_eapRespData(struct eap_sm *sm, const u8 *eapRespData, - size_t eapRespDataLen) -{ - if (sm == NULL) - return; - free(sm->eapRespData); - sm->eapRespData = malloc(eapRespDataLen); - if (sm->eapRespData == NULL) - return; - memcpy(sm->eapRespData, eapRespData, eapRespDataLen); - sm->eapRespDataLen = eapRespDataLen; - wpa_hexdump(MSG_MSGDUMP, "EAP: EAP-Response received", - eapRespData, eapRespDataLen); -} - - -static void eap_user_free(struct eap_user *user) -{ - if (user == NULL) - return; - free(user->password); - user->password = NULL; - free(user); -} - - -/** - * eap_sm_init - Allocate and initialize EAP 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_sm_init(void *eapol_ctx, struct eapol_callbacks *eapol_cb, - struct eap_config *conf) -{ - struct eap_sm *sm; - - sm = wpa_zalloc(sizeof(*sm)); - if (sm == NULL) - return NULL; - sm->eapol_ctx = eapol_ctx; - sm->eapol_cb = eapol_cb; - sm->MaxRetrans = 10; - sm->ssl_ctx = conf->ssl_ctx; - sm->eap_sim_db_priv = conf->eap_sim_db_priv; - sm->backend_auth = conf->backend_auth; - - wpa_printf(MSG_DEBUG, "EAP: State machine created"); - - return sm; -} - - -/** - * eap_sm_deinit - Deinitialize and free an EAP state machine - * @sm: Pointer to EAP state machine allocated with eap_sm_init() - * - * This function deinitializes EAP state machine and frees all allocated - * resources. - */ -void eap_sm_deinit(struct eap_sm *sm) -{ - if (sm == NULL) - return; - wpa_printf(MSG_DEBUG, "EAP: State machine removed"); - if (sm->m && sm->eap_method_priv) - sm->m->reset(sm, sm->eap_method_priv); - free(sm->eapReqData); - free(sm->eapKeyData); - free(sm->lastReqData); - free(sm->eapRespData); - free(sm->identity); - eap_user_free(sm->user); - free(sm); -} - - -/** - * eap_sm_notify_cached - Notify EAP state machine of cached PMK - * @sm: Pointer to EAP state machine allocated with eap_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_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_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_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) - * @msglen: Length of msg - * @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 u8 *msg, size_t msglen, size_t *plen) -{ - const struct eap_hdr *hdr; - const u8 *pos; - size_t len; - - hdr = (const struct eap_hdr *) msg; - - if (msglen < 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 > msglen) { - 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 - * @len: Buffer for returning message length - * @payload_len: Payload length in bytes (data after Type) - * @code: Message Code (EAP_CODE_*) - * @identifier: Identifier - * @payload: Pointer to payload pointer that will be set to point to the - * beginning of the payload or %NULL if payload pointer is not needed - * 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. - */ -struct eap_hdr * eap_msg_alloc(int vendor, EapType type, size_t *len, - size_t payload_len, u8 code, u8 identifier, - u8 **payload) -{ - struct eap_hdr *hdr; - u8 *pos; - - *len = sizeof(struct eap_hdr) + (vendor == EAP_VENDOR_IETF ? 1 : 8) + - payload_len; - hdr = malloc(*len); - if (hdr) { - hdr->code = code; - hdr->identifier = identifier; - hdr->length = host_to_be16(*len); - pos = (u8 *) (hdr + 1); - if (vendor == EAP_VENDOR_IETF) { - *pos++ = type; - } else { - *pos++ = EAP_TYPE_EXPANDED; - WPA_PUT_BE24(pos, vendor); - pos += 3; - WPA_PUT_BE32(pos, type); - pos += 4; - } - if (payload) - *payload = pos; - } - - return hdr; -} diff --git a/contrib/hostapd/eap.h b/contrib/hostapd/eap.h deleted file mode 100644 index 8fb1ec389e35..000000000000 --- a/contrib/hostapd/eap.h +++ /dev/null @@ -1,117 +0,0 @@ -/* $FreeBSD$ */ - -/* - * hostapd / EAP Standalone Authenticator state machine (RFC 4137) - * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "defs.h" -#include "eap_defs.h" -#include "eap_methods.h" - -struct eap_sm; - -#define EAP_MAX_METHODS 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; -}; - -enum eapol_bool_var { - EAPOL_eapSuccess, EAPOL_eapRestart, EAPOL_eapFail, EAPOL_eapResp, - EAPOL_eapReq, EAPOL_eapNoReq, EAPOL_portEnabled, EAPOL_eapTimeout -}; - -struct eapol_callbacks { - Boolean (*get_bool)(void *ctx, enum eapol_bool_var variable); - void (*set_bool)(void *ctx, enum eapol_bool_var variable, - Boolean value); - void (*set_eapReqData)(void *ctx, const u8 *eapReqData, - size_t eapReqDataLen); - void (*set_eapKeyData)(void *ctx, const u8 *eapKeyData, - size_t eapKeyDataLen); - 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 *eap_sim_db_priv; - Boolean backend_auth; -}; - - -#ifdef EAP_SERVER - -struct eap_sm * eap_sm_init(void *eapol_ctx, struct eapol_callbacks *eapol_cb, - struct eap_config *eap_conf); -void eap_sm_deinit(struct eap_sm *sm); -int eap_sm_step(struct eap_sm *sm); -void eap_set_eapRespData(struct eap_sm *sm, const u8 *eapRespData, - size_t eapRespDataLen); -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); - -#else /* EAP_SERVER */ - -static inline struct eap_sm * eap_sm_init(void *eapol_ctx, - struct eapol_callbacks *eapol_cb, - struct eap_config *eap_conf) -{ - return NULL; -} - -static inline void eap_sm_deinit(struct eap_sm *sm) -{ -} - -static inline int eap_sm_step(struct eap_sm *sm) -{ - return 0; -} - - -static inline void eap_set_eapRespData(struct eap_sm *sm, - const u8 *eapRespData, - size_t eapRespDataLen) -{ -} - -static inline void eap_sm_notify_cached(struct eap_sm *sm) -{ -} - -static inline void eap_sm_pending_cb(struct eap_sm *sm) -{ -} - -static inline int eap_sm_method_pending(struct eap_sm *sm) -{ - return 0; -} - -#endif /* EAP_SERVER */ - -#endif /* EAP_H */ diff --git a/contrib/hostapd/eap_aka.c b/contrib/hostapd/eap_aka.c deleted file mode 100644 index 9b10c8e1eb01..000000000000 --- a/contrib/hostapd/eap_aka.c +++ /dev/null @@ -1,862 +0,0 @@ -/* - * hostapd / EAP-AKA (RFC 4187) - * Copyright (c) 2005-2008, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "hostapd.h" -#include "common.h" -#include "crypto.h" -#include "eap_i.h" -#include "eap_sim_common.h" -#include "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_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[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; -}; - - -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 = wpa_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = IDENTITY; - eap_aka_determine_identity(sm, data, 1, 0); - - return data; -} - - -static void eap_aka_reset(struct eap_sm *sm, void *priv) -{ - struct eap_aka_data *data = priv; - free(data->next_pseudonym); - free(data->next_reauth_id); - free(data); -} - - -static u8 * eap_aka_build_identity(struct eap_sm *sm, - struct eap_aka_data *data, - int id, size_t *reqDataLen) -{ - struct eap_sim_msg *msg; - - wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Identity"); - msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_AKA, - 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); - } - return eap_sim_msg_finish(msg, reqDataLen, NULL, NULL, 0); -} - - -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) -{ - free(data->next_pseudonym); - data->next_pseudonym = - eap_sim_db_get_next_pseudonym(sm->eap_sim_db_priv, 1); - 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, - strlen(data->next_pseudonym), - (u8 *) data->next_pseudonym, - 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, - strlen(data->next_reauth_id), - (u8 *) data->next_reauth_id, - 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 u8 * eap_aka_build_challenge(struct eap_sm *sm, - struct eap_aka_data *data, - int id, size_t *reqDataLen) -{ - struct eap_sim_msg *msg; - - wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Challenge"); - msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_AKA, - 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); - eap_sim_msg_add(msg, EAP_SIM_AT_AUTN, 0, data->autn, EAP_AKA_AUTN_LEN); - - if (eap_aka_build_encr(sm, data, msg, 0, NULL)) { - 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, reqDataLen, data->k_aut, NULL, 0); -} - - -static u8 * eap_aka_build_reauth(struct eap_sm *sm, - struct eap_aka_data *data, - int id, size_t *reqDataLen) -{ - struct eap_sim_msg *msg; - - wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Re-authentication"); - - if (hostapd_get_rand(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); - - 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_AKA, - EAP_AKA_SUBTYPE_REAUTHENTICATION); - - if (eap_aka_build_encr(sm, data, msg, data->counter, data->nonce_s)) { - 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, reqDataLen, data->k_aut, NULL, 0); -} - - -static u8 * eap_aka_build_notification(struct eap_sm *sm, - struct eap_aka_data *data, - int id, size_t *reqDataLen) -{ - struct eap_sim_msg *msg; - - wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Notification"); - msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, EAP_TYPE_AKA, - EAP_AKA_SUBTYPE_NOTIFICATION); - wpa_printf(MSG_DEBUG, " AT_NOTIFICATION"); - eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, data->notification, - NULL, 0); - return eap_sim_msg_finish(msg, reqDataLen, NULL, NULL, 0); -} - - -static u8 * eap_aka_buildReq(struct eap_sm *sm, void *priv, int id, - size_t *reqDataLen) -{ - struct eap_aka_data *data = priv; - - data->auts_reported = 0; - switch (data->state) { - case IDENTITY: - return eap_aka_build_identity(sm, data, id, reqDataLen); - case CHALLENGE: - return eap_aka_build_challenge(sm, data, id, reqDataLen); - case REAUTH: - return eap_aka_build_reauth(sm, data, id, reqDataLen); - case NOTIFICATION: - return eap_aka_build_notification(sm, data, id, reqDataLen); - 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, - u8 *respData, size_t respDataLen) -{ - struct eap_hdr *resp; - u8 *pos; - - resp = (struct eap_hdr *) respData; - pos = (u8 *) (resp + 1); - if (respDataLen < sizeof(*resp) + 4 || *pos != EAP_TYPE_AKA || - (ntohs(resp->length)) > respDataLen) { - 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) { - 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; - 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; - } - - 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); - - 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, - u8 *respData, size_t respDataLen, - 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) { - free(sm->identity); - sm->identity = malloc(attr->identity_len); - if (sm->identity) { - memcpy(sm->identity, attr->identity, - attr->identity_len); - sm->identity_len = attr->identity_len; - } - } - - eap_aka_determine_identity(sm, data, 0, 0); -} - - -static void eap_aka_process_challenge(struct eap_sm *sm, - struct eap_aka_data *data, - u8 *respData, size_t respDataLen, - struct eap_sim_attrs *attr) -{ - const u8 *identity; - size_t identity_len; - - wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Challenge"); - - if (attr->mac == NULL || - eap_sim_verify_mac(data->k_aut, respData, respDataLen, 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; - } - - if (attr->res == NULL || attr->res_len != data->res_len || - memcmp(attr->res, data->res, data->res_len) != 0) { - wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message did not " - "include valid AT_RES"); - 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"); - 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) { - 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, - u8 *respData, size_t respDataLen, - 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, - u8 *respData, size_t respDataLen, - 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_sim_verify_mac(data->k_aut, respData, respDataLen, 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; - } - 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; - } - - 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) { - 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; - free(decrypted); -} - - -static void eap_aka_process_client_error(struct eap_sm *sm, - struct eap_aka_data *data, - u8 *respData, size_t respDataLen, - struct eap_sim_attrs *attr) -{ - wpa_printf(MSG_DEBUG, "EAP-AKA: Client reported error %d", - attr->client_error_code); - eap_aka_state(data, FAILURE); -} - - -static void eap_aka_process_authentication_reject( - struct eap_sm *sm, struct eap_aka_data *data, - u8 *respData, size_t respDataLen, 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, - u8 *respData, size_t respDataLen, - struct eap_sim_attrs *attr) -{ - wpa_printf(MSG_DEBUG, "EAP-AKA: Client replied to notification"); - eap_aka_state(data, FAILURE); -} - - -static void eap_aka_process(struct eap_sm *sm, void *priv, - u8 *respData, size_t respDataLen) -{ - struct eap_aka_data *data = priv; - struct eap_hdr *resp; - u8 *pos, subtype; - size_t len; - struct eap_sim_attrs attr; - - resp = (struct eap_hdr *) respData; - pos = (u8 *) (resp + 1); - subtype = pos[1]; - - 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; - } - - len = be_to_host16(resp->length); - pos += 4; - - if (eap_sim_parse_attr(pos, respData + len, &attr, 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, len, &attr); - return; - } - - if (subtype == EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT) { - eap_aka_process_authentication_reject(sm, data, respData, len, - &attr); - return; - } - - switch (data->state) { - case IDENTITY: - eap_aka_process_identity(sm, data, respData, len, &attr); - break; - case CHALLENGE: - if (subtype == EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE) { - eap_aka_process_sync_failure(sm, data, respData, len, - &attr); - } else { - eap_aka_process_challenge(sm, data, respData, len, - &attr); - } - break; - case REAUTH: - eap_aka_process_reauth(sm, data, respData, len, &attr); - break; - case NOTIFICATION: - eap_aka_process_notification(sm, data, respData, len, &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 = malloc(EAP_SIM_KEYING_DATA_LEN); - if (key == NULL) - return NULL; - 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 = malloc(EAP_EMSK_LEN); - if (key == NULL) - return NULL; - 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; -} diff --git a/contrib/hostapd/eap_defs.h b/contrib/hostapd/eap_defs.h deleted file mode 100644 index 8ea923a8f9d0..000000000000 --- a/contrib/hostapd/eap_defs.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * EAP server/peer: Shared EAP definitions - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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; - u16 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. */ - -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 /* draft-ietf-pppext-eap-ttls-02.txt */, - 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_FAST = 43 /* draft-cam-winget-eap-fast-05.txt */, - EAP_TYPE_PAX = 46 /* RFC 4746 */, - EAP_TYPE_PSK = 47 /* RFC 4764 */, - EAP_TYPE_SAKE = 48 /* RFC 4763 */, - EAP_TYPE_EXPANDED = 254 /* RFC 3748 */, - EAP_TYPE_GPSK = 255 /* EXPERIMENTAL - type not yet allocated - * draft-ietf-emu-eap-gpsk-01.txt */ -} EapType; - - -/* SMI Network Management Private Enterprise Code for vendor specific types */ -enum { - EAP_VENDOR_IETF = 0 -}; - -#define EAP_MSK_LEN 64 -#define EAP_EMSK_LEN 64 - -#endif /* EAP_DEFS_H */ diff --git a/contrib/hostapd/eap_gpsk.c b/contrib/hostapd/eap_gpsk.c deleted file mode 100644 index 3fecefe1ad18..000000000000 --- a/contrib/hostapd/eap_gpsk.c +++ /dev/null @@ -1,651 +0,0 @@ -/* - * hostapd / EAP-GPSK (draft-ietf-emu-eap-gpsk-08.txt) server - * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "hostapd.h" -#include "common.h" -#include "eap_i.h" -#include "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 = wpa_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = GPSK_1; - - /* TODO: add support for configuring ID_Server */ - data->id_server = (u8 *) strdup("hostapd"); - if (data->id_server) - data->id_server_len = 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; - free(data->id_server); - free(data->id_peer); - free(data); -} - - -static u8 * eap_gpsk_build_gpsk_1(struct eap_sm *sm, - struct eap_gpsk_data *data, - int id, size_t *reqDataLen) -{ - u8 *pos; - size_t len; - struct eap_hdr *req; - - wpa_printf(MSG_DEBUG, "EAP-GPSK: Request/GPSK-1"); - - if (hostapd_get_rand(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, reqDataLen, - len, EAP_CODE_REQUEST, id, &pos); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-GPSK: Failed to allocate memory " - "for request/GPSK-1"); - eap_gpsk_state(data, FAILURE); - return NULL; - } - - *pos++ = EAP_GPSK_OPCODE_GPSK_1; - - WPA_PUT_BE16(pos, data->id_server_len); - pos += 2; - if (data->id_server) - memcpy(pos, data->id_server, data->id_server_len); - pos += data->id_server_len; - - memcpy(pos, data->rand_server, EAP_GPSK_RAND_LEN); - pos += EAP_GPSK_RAND_LEN; - - WPA_PUT_BE16(pos, data->csuite_count * sizeof(struct eap_gpsk_csuite)); - pos += 2; - memcpy(pos, data->csuite_list, - data->csuite_count * sizeof(struct eap_gpsk_csuite)); - - return (u8 *) req; -} - - -static u8 * eap_gpsk_build_gpsk_3(struct eap_sm *sm, - struct eap_gpsk_data *data, - int id, size_t *reqDataLen) -{ - u8 *pos, *start; - size_t len, miclen; - struct eap_gpsk_csuite *csuite; - struct eap_hdr *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, reqDataLen, - len, EAP_CODE_REQUEST, id, &pos); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-GPSK: Failed to allocate memory " - "for request/GPSK-3"); - eap_gpsk_state(data, FAILURE); - return NULL; - } - - *pos++ = EAP_GPSK_OPCODE_GPSK_3; - start = pos; - - memcpy(pos, data->rand_peer, EAP_GPSK_RAND_LEN); - pos += EAP_GPSK_RAND_LEN; - memcpy(pos, data->rand_server, EAP_GPSK_RAND_LEN); - pos += EAP_GPSK_RAND_LEN; - WPA_PUT_BE16(pos, data->id_server_len); - pos += 2; - if (data->id_server) - memcpy(pos, data->id_server, data->id_server_len); - pos += data->id_server_len; - csuite = (struct eap_gpsk_csuite *) pos; - WPA_PUT_BE32(csuite->vendor, data->vendor); - WPA_PUT_BE16(csuite->specifier, data->specifier); - pos += sizeof(*csuite); - - /* no PD_Payload_2 */ - WPA_PUT_BE16(pos, 0); - pos += 2; - - if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor, - data->specifier, start, pos - start, pos) < 0) - { - free(req); - eap_gpsk_state(data, FAILURE); - return NULL; - } - - return (u8 *) req; -} - - -static u8 * eap_gpsk_buildReq(struct eap_sm *sm, void *priv, int id, - size_t *reqDataLen) -{ - struct eap_gpsk_data *data = priv; - - switch (data->state) { - case GPSK_1: - return eap_gpsk_build_gpsk_1(sm, data, id, reqDataLen); - case GPSK_3: - return eap_gpsk_build_gpsk_3(sm, data, id, reqDataLen); - 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, - u8 *respData, size_t respDataLen) -{ - struct eap_gpsk_data *data = priv; - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, - respData, respDataLen, &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, - u8 *respData, size_t respDataLen, - 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; - } - free(data->id_peer); - data->id_peer = malloc(alen); - if (data->id_peer == NULL) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Not enough memory to store " - "%d-octet ID_Peer", alen); - return; - } - 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 || - 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; - } - 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 (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) || - 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 (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=%d miclen=%d)", end - pos, 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 (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 %d bytes of extra " - "data in the end of GPSK-2", end - pos); - } - - eap_gpsk_state(data, GPSK_3); -} - - -static void eap_gpsk_process_gpsk_4(struct eap_sm *sm, - struct eap_gpsk_data *data, - u8 *respData, size_t respDataLen, - 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=%d miclen=%d)", end - pos, 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 (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 %d bytes of extra " - "data in the end of GPSK-4", end - pos); - } - - eap_gpsk_state(data, SUCCESS); -} - - -static void eap_gpsk_process(struct eap_sm *sm, void *priv, - u8 *respData, size_t respDataLen) -{ - struct eap_gpsk_data *data = priv; - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, - respData, respDataLen, &len); - if (pos == NULL || len < 1) - return; - - switch (*pos) { - case EAP_GPSK_OPCODE_GPSK_2: - eap_gpsk_process_gpsk_2(sm, data, respData, respDataLen, - pos + 1, len - 1); - break; - case EAP_GPSK_OPCODE_GPSK_4: - eap_gpsk_process_gpsk_4(sm, data, respData, respDataLen, - 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 = malloc(EAP_MSK_LEN); - if (key == NULL) - return NULL; - 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 = malloc(EAP_EMSK_LEN); - if (key == NULL) - return NULL; - 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/contrib/hostapd/eap_gpsk_common.c b/contrib/hostapd/eap_gpsk_common.c deleted file mode 100644 index 7422fa6c48f9..000000000000 --- a/contrib/hostapd/eap_gpsk_common.c +++ /dev/null @@ -1,425 +0,0 @@ -/* - * EAP server/peer: EAP-GPSK shared routines - * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "aes_wrap.h" -#include "crypto.h" -#ifdef EAP_GPSK_SHA256 -#include "sha256.h" -#endif /* EAP_GPSK_SHA256 */ -#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); - omac1_aes_128_vector(psk, 2, addr, vlen, hash); - 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 %d for " - "AES-CMAC MIC", 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/contrib/hostapd/eap_gpsk_common.h b/contrib/hostapd/eap_gpsk_common.h deleted file mode 100644 index a30ab97ffa07..000000000000 --- a/contrib/hostapd/eap_gpsk_common.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * EAP server/peer: EAP-GPSK shared routines - * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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/contrib/hostapd/eap_gtc.c b/contrib/hostapd/eap_gtc.c deleted file mode 100644 index 42e4cd35cd74..000000000000 --- a/contrib/hostapd/eap_gtc.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * hostapd / EAP-GTC (RFC 3748) - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "hostapd.h" -#include "common.h" -#include "eap_i.h" - - -struct eap_gtc_data { - enum { CONTINUE, SUCCESS, FAILURE } state; -}; - - -static void * eap_gtc_init(struct eap_sm *sm) -{ - struct eap_gtc_data *data; - - data = wpa_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = CONTINUE; - - return data; -} - - -static void eap_gtc_reset(struct eap_sm *sm, void *priv) -{ - struct eap_gtc_data *data = priv; - free(data); -} - - -static u8 * eap_gtc_buildReq(struct eap_sm *sm, void *priv, int id, - size_t *reqDataLen) -{ - struct eap_gtc_data *data = priv; - struct eap_hdr *req; - u8 *pos; - char *msg = "Password"; - size_t msg_len; - - msg_len = strlen(msg); - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GTC, reqDataLen, - msg_len, EAP_CODE_REQUEST, id, &pos); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-GTC: Failed to allocate memory for " - "request"); - data->state = FAILURE; - return NULL; - } - - memcpy(pos, msg, msg_len); - - data->state = CONTINUE; - - return (u8 *) req; -} - - -static Boolean eap_gtc_check(struct eap_sm *sm, void *priv, - u8 *respData, size_t respDataLen) -{ - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GTC, - respData, respDataLen, &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, - u8 *respData, size_t respDataLen) -{ - struct eap_gtc_data *data = priv; - const u8 *pos; - size_t rlen; - - 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; - } - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GTC, - respData, respDataLen, &rlen); - if (pos == NULL || rlen < 1) - return; /* Should not happen - frame already validated */ - - wpa_hexdump_key(MSG_MSGDUMP, "EAP-GTC: Response", pos, rlen); - - if (rlen != sm->user->password_len || - 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/contrib/hostapd/eap_i.h b/contrib/hostapd/eap_i.h deleted file mode 100644 index 85b2c2d2fac8..000000000000 --- a/contrib/hostapd/eap_i.h +++ /dev/null @@ -1,192 +0,0 @@ -/* - * hostapd / EAP Authenticator state machine internal structures (RFC 4137) - * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "eap.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); - - u8 * (*buildReq)(struct eap_sm *sm, void *priv, int id, - size_t *reqDataLen); - int (*getTimeout)(struct eap_sm *sm, void *priv); - Boolean (*check)(struct eap_sm *sm, void *priv, - u8 *respData, size_t respDataLen); - void (*process)(struct eap_sm *sm, void *priv, - u8 *respData, size_t respDataLen); - 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_state; - - /* Constants */ - int MaxRetrans; - - /* Lower layer to standalone authenticator variables */ - /* eapResp: eapol_sm->be_auth.eapResp */ - /* portEnabled: eapol_sm->portEnabled */ - /* eapRestart: eapol_sm->auth_pae.eapRestart */ - u8 *eapRespData; - size_t eapRespDataLen; - int retransWhile; - int eapSRTT; - int eapRTTVAR; - - /* Standalone authenticator to lower layer variables */ - /* eapReq: eapol_sm->be_auth.eapReq */ - /* eapNoReq: eapol_sm->be_auth.eapNoReq */ - /* eapSuccess: eapol_sm->eapSuccess */ - /* eapFail: eapol_sm->eapFail */ - /* eapTimeout: eapol_sm->eapTimeout */ - u8 *eapReqData; - size_t eapReqDataLen; - u8 *eapKeyData; /* also eapKeyAvailable (boolean) */ - size_t eapKeyDataLen; - - /* Standalone authenticator state machine local variables */ - - /* Long-term (maintained betwen packets) */ - EapType currentMethod; - int currentId; - enum { - METHOD_PROPOSED, METHOD_CONTINUE, METHOD_END - } methodState; - int retransCount; - u8 *lastReqData; - size_t lastReqDataLen; - 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; - - /* Miscellaneous variables */ - const struct eap_method *m; /* selected EAP method */ - /* not defined in draft-ietf-eap-statemachine-02 */ - Boolean changed; - void *eapol_ctx, *msg_ctx; - struct eapol_callbacks *eapol_cb; - void *eap_method_priv; - u8 *identity; - size_t identity_len; - int lastId; /* Identifier used in the last EAP-Packet */ - struct eap_user *user; - int user_eap_method_index; - int init_phase2; - void *ssl_ctx; - enum { TLV_REQ_NONE, TLV_REQ_SUCCESS, TLV_REQ_FAILURE } tlv_request; - void *eap_sim_db_priv; - Boolean backend_auth; - Boolean update_user; - - int num_rounds; - enum { - METHOD_PENDING_NONE, METHOD_PENDING_WAIT, METHOD_PENDING_CONT - } method_pending; -}; - -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, u8 *nak_list, size_t len); -const u8 * eap_hdr_validate(int vendor, EapType eap_type, - const u8 *msg, size_t msglen, size_t *plen); -struct eap_hdr * eap_msg_alloc(int vendor, EapType type, size_t *len, - size_t payload_len, u8 code, u8 identifier, - u8 **payload); - -#endif /* EAP_I_H */ diff --git a/contrib/hostapd/eap_identity.c b/contrib/hostapd/eap_identity.c deleted file mode 100644 index ab6f26b1fea5..000000000000 --- a/contrib/hostapd/eap_identity.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * hostapd / EAP-Identity - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "hostapd.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 = wpa_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; - free(data); -} - - -static u8 * eap_identity_buildReq(struct eap_sm *sm, void *priv, int id, - size_t *reqDataLen) -{ - struct eap_identity_data *data = priv; - struct eap_hdr *req; - u8 *pos; - 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, reqDataLen, - req_data_len, EAP_CODE_REQUEST, id, &pos); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-Identity: Failed to allocate " - "memory for request"); - data->state = FAILURE; - return NULL; - } - - if (req_data) - memcpy(pos, req_data, req_data_len); - - return (u8 *) req; -} - - -static Boolean eap_identity_check(struct eap_sm *sm, void *priv, - u8 *respData, size_t respDataLen) -{ - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, - respData, respDataLen, &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, - u8 *respData, size_t respDataLen) -{ - struct eap_identity_data *data = priv; - const u8 *pos; - size_t len; - - if (data->pick_up) { - if (eap_identity_check(sm, data, respData, respDataLen)) { - 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, respDataLen, &len); - if (pos == NULL) - return; /* Should not happen - frame already validated */ - - wpa_hexdump_ascii(MSG_DEBUG, "EAP-Identity: Peer identity", pos, len); - free(sm->identity); - sm->identity = malloc(len); - if (sm->identity == NULL) { - data->state = FAILURE; - } else { - 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/contrib/hostapd/eap_md5.c b/contrib/hostapd/eap_md5.c deleted file mode 100644 index 234a319b6909..000000000000 --- a/contrib/hostapd/eap_md5.c +++ /dev/null @@ -1,188 +0,0 @@ -/* - * hostapd / EAP-MD5 server - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "hostapd.h" -#include "common.h" -#include "eap_i.h" -#include "md5.h" -#include "crypto.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 = wpa_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; - free(data); -} - - -static u8 * eap_md5_buildReq(struct eap_sm *sm, void *priv, int id, - size_t *reqDataLen) -{ - struct eap_md5_data *data = priv; - struct eap_hdr *req; - u8 *pos; - - if (hostapd_get_rand(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, reqDataLen, - 1 + CHALLENGE_LEN, EAP_CODE_REQUEST, id, &pos); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-MD5: Failed to allocate memory for " - "request"); - data->state = FAILURE; - return NULL; - } - - *pos++ = CHALLENGE_LEN; - memcpy(pos, data->challenge, CHALLENGE_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Challenge", pos, CHALLENGE_LEN); - - data->state = CONTINUE; - - return (u8 *) req; -} - - -static Boolean eap_md5_check(struct eap_sm *sm, void *priv, - u8 *respData, size_t respDataLen) -{ - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MD5, - respData, respDataLen, &len); - if (pos == NULL || len < 1) { - wpa_printf(MSG_INFO, "EAP-MD5: Invalid frame"); - return TRUE; - } - if (*pos != MD5_MAC_LEN || 1 + MD5_MAC_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, - u8 *respData, size_t respDataLen) -{ - struct eap_md5_data *data = priv; - struct eap_hdr *resp; - const u8 *pos; - const u8 *addr[3]; - size_t len[3], plen; - u8 hash[MD5_MAC_LEN]; - - 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, respDataLen, &plen); - if (pos == NULL || *pos != MD5_MAC_LEN || plen < 1 + MD5_MAC_LEN) - return; /* Should not happen - frame already validated */ - - pos++; /* Skip response len */ - wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Response", pos, MD5_MAC_LEN); - - resp = (struct eap_hdr *) respData; - addr[0] = &resp->identifier; - len[0] = 1; - addr[1] = sm->user->password; - len[1] = sm->user->password_len; - addr[2] = data->challenge; - len[2] = CHALLENGE_LEN; - md5_vector(3, addr, len, hash); - - if (memcmp(hash, pos, MD5_MAC_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/contrib/hostapd/eap_methods.c b/contrib/hostapd/eap_methods.c deleted file mode 100644 index 671d5486c316..000000000000 --- a/contrib/hostapd/eap_methods.c +++ /dev/null @@ -1,273 +0,0 @@ -/* - * hostapd / EAP method registration - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "hostapd.h" -#include "eap_i.h" -#include "eap_methods.h" - - -static struct eap_method *eap_methods; - - -/** - * eap_sm_get_eap_methods - 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_sm_get_eap_methods(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_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_get_type(const char *name, int *vendor) -{ - struct eap_method *m; - for (m = eap_methods; m; m = m->next) { - if (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 = wpa_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) -{ - 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) || - strcmp(m->name, method->name) == 0) - return -2; - last = m; - } - - if (last) - last->next = method; - else - eap_methods = method; - - return 0; -} - - -/** - * eap_server_register_methods - Register statically linked EAP server methods - * Returns: 0 on success, -1 on failure - * - * This function is called at program initialization to register all EAP server - * methods that were linked in statically. - */ -int eap_server_register_methods(void) -{ - int ret = 0; - - if (ret == 0) { - int eap_server_identity_register(void); - ret = eap_server_identity_register(); - } - -#ifdef EAP_MD5 - if (ret == 0) { - int eap_server_md5_register(void); - ret = eap_server_md5_register(); - } -#endif /* EAP_MD5 */ - -#ifdef EAP_TLS - if (ret == 0) { - int eap_server_tls_register(void); - ret = eap_server_tls_register(); - } -#endif /* EAP_TLS */ - -#ifdef EAP_MSCHAPv2 - if (ret == 0) { - int eap_server_mschapv2_register(void); - ret = eap_server_mschapv2_register(); - } -#endif /* EAP_MSCHAPv2 */ - -#ifdef EAP_PEAP - if (ret == 0) { - int eap_server_peap_register(void); - ret = eap_server_peap_register(); - } -#endif /* EAP_PEAP */ - -#ifdef EAP_TLV - if (ret == 0) { - int eap_server_tlv_register(void); - ret = eap_server_tlv_register(); - } -#endif /* EAP_TLV */ - -#ifdef EAP_GTC - if (ret == 0) { - int eap_server_gtc_register(void); - ret = eap_server_gtc_register(); - } -#endif /* EAP_GTC */ - -#ifdef EAP_TTLS - if (ret == 0) { - int eap_server_ttls_register(void); - ret = eap_server_ttls_register(); - } -#endif /* EAP_TTLS */ - -#ifdef EAP_SIM - if (ret == 0) { - int eap_server_sim_register(void); - ret = eap_server_sim_register(); - } -#endif /* EAP_SIM */ - -#ifdef EAP_AKA - if (ret == 0) { - int eap_server_aka_register(void); - ret = eap_server_aka_register(); - } -#endif /* EAP_AKA */ - -#ifdef EAP_PAX - if (ret == 0) { - int eap_server_pax_register(void); - ret = eap_server_pax_register(); - } -#endif /* EAP_PAX */ - -#ifdef EAP_PSK - if (ret == 0) { - int eap_server_psk_register(void); - ret = eap_server_psk_register(); - } -#endif /* EAP_PSK */ - -#ifdef EAP_SAKE - if (ret == 0) { - int eap_server_sake_register(void); - ret = eap_server_sake_register(); - } -#endif /* EAP_SAKE */ - -#ifdef EAP_GPSK - if (ret == 0) { - int eap_server_gpsk_register(void); - ret = eap_server_gpsk_register(); - } -#endif /* EAP_GPSK */ - -#ifdef EAP_VENDOR_TEST - if (ret == 0) { - int eap_server_vendor_test_register(void); - ret = eap_server_vendor_test_register(); - } -#endif /* EAP_VENDOR_TEST */ - - return ret; -} - - -/** - * 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); - } -} diff --git a/contrib/hostapd/eap_methods.h b/contrib/hostapd/eap_methods.h deleted file mode 100644 index cec8a570e2a6..000000000000 --- a/contrib/hostapd/eap_methods.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * hostapd / EAP method registration - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 - -const struct eap_method * eap_sm_get_eap_methods(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); - -#ifdef EAP_SERVER - -EapType eap_get_type(const char *name, int *vendor); -int eap_server_register_methods(void); -void eap_server_unregister_methods(void); - -#else /* EAP_SERVER */ - -static inline EapType eap_get_type(const char *name, int *vendor) -{ - *vendor = EAP_VENDOR_IETF; - return EAP_TYPE_NONE; -} - -static inline int eap_server_register_methods(void) -{ - return 0; -} - -static inline void eap_server_unregister_methods(void) -{ -} - -#endif /* EAP_SERVER */ - -#endif /* EAP_METHODS_H */ diff --git a/contrib/hostapd/eap_mschapv2.c b/contrib/hostapd/eap_mschapv2.c deleted file mode 100644 index bbd819bbe12b..000000000000 --- a/contrib/hostapd/eap_mschapv2.c +++ /dev/null @@ -1,555 +0,0 @@ -/* - * hostapd / EAP-MSCHAPv2 (draft-kamath-pppext-eap-mschapv2-00.txt) server - * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "hostapd.h" -#include "common.h" -#include "eap_i.h" -#include "ms_funcs.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]; - 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 = wpa_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = CHALLENGE; - - return data; -} - - -static void eap_mschapv2_reset(struct eap_sm *sm, void *priv) -{ - struct eap_mschapv2_data *data = priv; - free(data); -} - - -static u8 * eap_mschapv2_build_challenge(struct eap_sm *sm, - struct eap_mschapv2_data *data, - int id, size_t *reqDataLen) -{ - struct eap_hdr *req; - struct eap_mschapv2_hdr *ms; - u8 *pos; - char *name = "hostapd"; /* TODO: make this configurable */ - size_t ms_len; - - if (hostapd_get_rand(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 + strlen(name); - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, reqDataLen, - ms_len, EAP_CODE_REQUEST, id, &pos); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to allocate memory" - " for request"); - data->state = FAILURE; - return NULL; - } - - ms = (struct eap_mschapv2_hdr *) pos; - ms->op_code = MSCHAPV2_OP_CHALLENGE; - ms->mschapv2_id = id; - WPA_PUT_BE16(ms->ms_length, ms_len); - - pos = (u8 *) (ms + 1); - *pos++ = CHALLENGE_LEN; - memcpy(pos, data->auth_challenge, CHALLENGE_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-MSCHAPV2: Challenge", pos, - CHALLENGE_LEN); - pos += CHALLENGE_LEN; - memcpy(pos, name, strlen(name)); - - return (u8 *) req; -} - - -static u8 * eap_mschapv2_build_success_req(struct eap_sm *sm, - struct eap_mschapv2_data *data, - int id, size_t *reqDataLen) -{ - struct eap_hdr *req; - struct eap_mschapv2_hdr *ms; - u8 *pos, *msg; - char *message = "OK"; - size_t ms_len; - - ms_len = sizeof(*ms) + 2 + 2 * sizeof(data->auth_response) + 1 + 2 + - strlen(message); - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, reqDataLen, - ms_len, EAP_CODE_REQUEST, id, &pos); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to allocate memory" - " for request"); - data->state = FAILURE; - return NULL; - } - - ms = (struct eap_mschapv2_hdr *) pos; - ms->op_code = MSCHAPV2_OP_SUCCESS; - ms->mschapv2_id = data->resp_mschapv2_id; - WPA_PUT_BE16(ms->ms_length, ms_len); - - msg = pos = (u8 *) (ms + 1); - *pos++ = 'S'; - *pos++ = '='; - pos += wpa_snprintf_hex_uppercase((char *) pos, - sizeof(data->auth_response) * 2 + 1, - data->auth_response, - sizeof(data->auth_response)); - *pos++ = ' '; - *pos++ = 'M'; - *pos++ = '='; - memcpy(pos, message, strlen(message)); - - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-MSCHAPV2: Success Request Message", - msg, ms_len - sizeof(*ms)); - - return (u8 *) req; -} - - -static u8 * eap_mschapv2_build_failure_req(struct eap_sm *sm, - struct eap_mschapv2_data *data, - int id, size_t *reqDataLen) -{ - struct eap_hdr *req; - struct eap_mschapv2_hdr *ms; - u8 *pos; - char *message = "E=691 R=0 C=00000000000000000000000000000000 V=3 " - "M=FAILED"; - size_t ms_len; - - ms_len = sizeof(*ms) + strlen(message); - req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, reqDataLen, - ms_len, EAP_CODE_REQUEST, id, &pos); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Failed to allocate memory" - " for request"); - data->state = FAILURE; - return NULL; - } - - ms = (struct eap_mschapv2_hdr *) pos; - ms->op_code = MSCHAPV2_OP_FAILURE; - ms->mschapv2_id = data->resp_mschapv2_id; - WPA_PUT_BE16(ms->ms_length, ms_len); - - memcpy((u8 *) (ms + 1), message, strlen(message)); - - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-MSCHAPV2: Failure Request Message", - (u8 *) message, strlen(message)); - - return (u8 *) req; -} - - -static u8 * eap_mschapv2_buildReq(struct eap_sm *sm, void *priv, int id, - size_t *reqDataLen) -{ - struct eap_mschapv2_data *data = priv; - - switch (data->state) { - case CHALLENGE: - return eap_mschapv2_build_challenge(sm, data, id, reqDataLen); - case SUCCESS_REQ: - return eap_mschapv2_build_success_req(sm, data, id, - reqDataLen); - case FAILURE_REQ: - return eap_mschapv2_build_failure_req(sm, data, id, - reqDataLen); - 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, - u8 *respData, size_t respDataLen) -{ - 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, respDataLen, &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, - u8 *respData, size_t respDataLen) -{ - 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; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, - respData, respDataLen, &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(MSG_DEBUG, "EAP-MSCHAPV2: Invalid response", - respData, respDataLen); - 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; - - 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 || - 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) { - generate_nt_response_pwhash(data->auth_challenge, - peer_challenge, - username, username_len, - sm->user->password, - expected); - } else { - generate_nt_response(data->auth_challenge, peer_challenge, - username, username_len, - sm->user->password, - sm->user->password_len, - expected); - } - - if (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; - generate_authenticator_response_pwhash( - sm->user->password, peer_challenge, - data->auth_challenge, username, username_len, - nt_response, data->auth_response); - } else { - nt_password_hash(sm->user->password, - sm->user->password_len, - pw_hash_buf); - pw_hash = pw_hash_buf; - generate_authenticator_response(sm->user->password, - sm->user->password_len, - 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, - u8 *respData, size_t respDataLen) -{ - struct eap_mschapv2_hdr *resp; - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, - respData, respDataLen, &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, - u8 *respData, size_t respDataLen) -{ - struct eap_mschapv2_hdr *resp; - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, - respData, respDataLen, &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, - u8 *respData, size_t respDataLen) -{ - 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, respDataLen); - break; - case SUCCESS_REQ: - eap_mschapv2_process_success_resp(sm, data, respData, - respDataLen); - break; - case FAILURE_REQ: - eap_mschapv2_process_failure_resp(sm, data, respData, - respDataLen); - 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 = malloc(*len); - if (key == NULL) - return NULL; - get_asymetric_start_key(data->master_key, key, MSCHAPV2_KEY_LEN, 0, 0); - get_asymetric_start_key(data->master_key, key + MSCHAPV2_KEY_LEN, - MSCHAPV2_KEY_LEN, 1, 0); - 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/contrib/hostapd/eap_pax.c b/contrib/hostapd/eap_pax.c deleted file mode 100644 index 8daa8d3adb04..000000000000 --- a/contrib/hostapd/eap_pax.c +++ /dev/null @@ -1,562 +0,0 @@ -/* - * hostapd / EAP-PAX (RFC 4746) server - * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "hostapd.h" -#include "common.h" -#include "eap_i.h" -#include "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 = wpa_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; - free(data->cid); - free(data); -} - - -static u8 * eap_pax_build_std_1(struct eap_sm *sm, - struct eap_pax_data *data, - int id, size_t *reqDataLen) -{ - struct eap_pax_hdr *req; - u8 *pos; - - wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-1 (sending)"); - - if (hostapd_get_rand(data->rand.r.x, EAP_PAX_RAND_LEN)) { - wpa_printf(MSG_ERROR, "EAP-PAX: Failed to get random data"); - data->state = FAILURE; - return NULL; - } - - *reqDataLen = sizeof(*req) + 2 + EAP_PAX_RAND_LEN + EAP_PAX_ICV_LEN; - req = malloc(*reqDataLen); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-PAX: Failed to allocate memory " - "request"); - data->state = FAILURE; - return NULL; - } - - req->code = EAP_CODE_REQUEST; - req->identifier = id; - req->length = htons(*reqDataLen); - req->type = EAP_TYPE_PAX; - req->op_code = EAP_PAX_OP_STD_1; - req->flags = 0; - req->mac_id = data->mac_id; - req->dh_group_id = EAP_PAX_DH_GROUP_NONE; - req->public_key_id = EAP_PAX_PUBLIC_KEY_NONE; - pos = (u8 *) (req + 1); - *pos++ = 0; - *pos++ = EAP_PAX_RAND_LEN; - memcpy(pos, data->rand.r.x, EAP_PAX_RAND_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: A = X (server rand)", - pos, EAP_PAX_RAND_LEN); - pos += EAP_PAX_RAND_LEN; - - eap_pax_mac(data->mac_id, (u8 *) "", 0, - (u8 *) req, *reqDataLen - EAP_PAX_ICV_LEN, - NULL, 0, NULL, 0, pos); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", pos, EAP_PAX_ICV_LEN); - pos += EAP_PAX_ICV_LEN; - - return (u8 *) req; -} - - -static u8 * eap_pax_build_std_3(struct eap_sm *sm, - struct eap_pax_data *data, - int id, size_t *reqDataLen) -{ - struct eap_pax_hdr *req; - u8 *pos; - - wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-3 (sending)"); - - *reqDataLen = sizeof(*req) + 2 + EAP_PAX_MAC_LEN + EAP_PAX_ICV_LEN; - req = malloc(*reqDataLen); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-PAX: Failed to allocate memory " - "request"); - data->state = FAILURE; - return NULL; - } - - req->code = EAP_CODE_REQUEST; - req->identifier = id; - req->length = htons(*reqDataLen); - req->type = EAP_TYPE_PAX; - req->op_code = EAP_PAX_OP_STD_3; - req->flags = 0; - req->mac_id = data->mac_id; - req->dh_group_id = EAP_PAX_DH_GROUP_NONE; - req->public_key_id = EAP_PAX_PUBLIC_KEY_NONE; - pos = (u8 *) (req + 1); - *pos++ = 0; - *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, 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 */ - - eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN, - (u8 *) req, *reqDataLen - EAP_PAX_ICV_LEN, - NULL, 0, NULL, 0, pos); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", pos, EAP_PAX_ICV_LEN); - pos += EAP_PAX_ICV_LEN; - - return (u8 *) req; -} - - -static u8 * eap_pax_buildReq(struct eap_sm *sm, void *priv, int id, - size_t *reqDataLen) -{ - struct eap_pax_data *data = priv; - - switch (data->state) { - case PAX_STD_1: - return eap_pax_build_std_1(sm, data, id, reqDataLen); - case PAX_STD_3: - return eap_pax_build_std_3(sm, data, id, reqDataLen); - 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, - u8 *respData, size_t respDataLen) -{ - struct eap_pax_data *data = priv; - struct eap_pax_hdr *resp; - size_t len; - u8 icvbuf[EAP_PAX_ICV_LEN], *icv; - - resp = (struct eap_pax_hdr *) respData; - if (respDataLen < sizeof(*resp) || resp->type != EAP_TYPE_PAX || - (len = ntohs(resp->length)) > respDataLen || - len < sizeof(*resp) + EAP_PAX_ICV_LEN) { - wpa_printf(MSG_INFO, "EAP-PAX: Invalid frame"); - return TRUE; - } - - 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 = respData + len - 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, - respData, len - EAP_PAX_ICV_LEN, NULL, 0, NULL, 0, - icvbuf); - if (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, - u8 *respData, size_t respDataLen) -{ - struct eap_pax_hdr *resp; - u8 *pos, mac[EAP_PAX_MAC_LEN], icvbuf[EAP_PAX_ICV_LEN]; - size_t len, left; - int i; - - if (data->state != PAX_STD_1) - return; - - wpa_printf(MSG_DEBUG, "EAP-PAX: Received PAX_STD-2"); - - resp = (struct eap_pax_hdr *) respData; - len = ntohs(resp->length); - pos = (u8 *) (resp + 1); - left = len - sizeof(*resp); - - if (left < 2 + EAP_PAX_RAND_LEN || - ((pos[0] << 8) | pos[1]) != EAP_PAX_RAND_LEN) { - wpa_printf(MSG_INFO, "EAP-PAX: Too short PAX_STD-2 (B)"); - return; - } - pos += 2; - left -= 2; - 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 + ((pos[0] << 8) | pos[1]) > left) { - wpa_printf(MSG_INFO, "EAP-PAX: Too short PAX_STD-2 (CID)"); - return; - } - data->cid_len = (pos[0] << 8) | pos[1]; - free(data->cid); - data->cid = malloc(data->cid_len); - if (data->cid == NULL) { - wpa_printf(MSG_INFO, "EAP-PAX: Failed to allocate memory for " - "CID"); - return; - } - 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 || - ((pos[0] << 8) | pos[1]) != 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; - } - 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 (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, - respData, len - EAP_PAX_ICV_LEN, NULL, 0, NULL, 0, icvbuf); - if (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, - u8 *respData, size_t respDataLen) -{ - 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, - u8 *respData, size_t respDataLen) -{ - struct eap_pax_data *data = priv; - struct eap_pax_hdr *resp; - - if (sm->user == NULL || sm->user->password == NULL) { - wpa_printf(MSG_INFO, "EAP-PAX: Plaintext password not " - "configured"); - data->state = FAILURE; - return; - } - - resp = (struct eap_pax_hdr *) respData; - - switch (resp->op_code) { - case EAP_PAX_OP_STD_2: - eap_pax_process_std_2(sm, data, respData, respDataLen); - break; - case EAP_PAX_OP_ACK: - eap_pax_process_ack(sm, data, respData, respDataLen); - 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 = 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 = 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/contrib/hostapd/eap_pax_common.c b/contrib/hostapd/eap_pax_common.c deleted file mode 100644 index 80110469dcc3..000000000000 --- a/contrib/hostapd/eap_pax_common.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * EAP server/peer: EAP-PAX shared routines - * Copyright (c) 2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "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/contrib/hostapd/eap_pax_common.h b/contrib/hostapd/eap_pax_common.h deleted file mode 100644 index bbad5e4052ff..000000000000 --- a/contrib/hostapd/eap_pax_common.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * EAP server/peer: EAP-PAX shared routines - * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 code; - u8 identifier; - u16 length; /* including code, identifier, and length */ - u8 type; /* EAP_TYPE_PAX */ - 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/contrib/hostapd/eap_peap.c b/contrib/hostapd/eap_peap.c deleted file mode 100644 index 6ea1f618a1d8..000000000000 --- a/contrib/hostapd/eap_peap.c +++ /dev/null @@ -1,731 +0,0 @@ -/* - * hostapd / EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-07.txt) - * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "hostapd.h" -#include "common.h" -#include "eap_i.h" -#include "eap_tls_common.h" -#include "tls.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-07.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, PHASE2_START, PHASE2_ID, PHASE2_METHOD, - PHASE2_TLV, SUCCESS_REQ, FAILURE_REQ, SUCCESS, FAILURE - } state; - - int peap_version; - const struct eap_method *phase2_method; - void *phase2_priv; - int force_version; -}; - - -static const char * eap_peap_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 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 EapType 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 EAP_TYPE_NONE; - } - - if (data->peap_version == 0) { - sm->tlv_request = TLV_REQ_SUCCESS; - eap_peap_state(data, PHASE2_TLV); - return EAP_TYPE_TLV; - } else { - eap_peap_state(data, SUCCESS_REQ); - return EAP_TYPE_NONE; - } -} - - -static EapType 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->phase2_method && - data->phase2_method->method == EAP_TYPE_TLV)) { - eap_peap_state(data, FAILURE); - return EAP_TYPE_NONE; - } - - if (data->peap_version == 0) { - sm->tlv_request = TLV_REQ_FAILURE; - eap_peap_state(data, PHASE2_TLV); - return EAP_TYPE_TLV; - } else { - eap_peap_state(data, FAILURE_REQ); - return EAP_TYPE_NONE; - } -} - - -static void * eap_peap_init(struct eap_sm *sm) -{ - struct eap_peap_data *data; - - data = wpa_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; - - if (eap_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_tls_ssl_deinit(sm, &data->ssl); - free(data); -} - - -static u8 * eap_peap_build_start(struct eap_sm *sm, struct eap_peap_data *data, - int id, size_t *reqDataLen) -{ - struct eap_hdr *req; - u8 *pos; - - *reqDataLen = sizeof(*req) + 2; - req = malloc(*reqDataLen); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-PEAP: Failed to allocate memory for" - " request"); - eap_peap_state(data, FAILURE); - return NULL; - } - - req->code = EAP_CODE_REQUEST; - req->identifier = id; - req->length = htons(*reqDataLen); - pos = (u8 *) (req + 1); - *pos++ = EAP_TYPE_PEAP; - *pos = EAP_TLS_FLAGS_START | data->peap_version; - - eap_peap_state(data, PHASE1); - - return (u8 *) req; -} - - -static u8 * eap_peap_build_req(struct eap_sm *sm, struct eap_peap_data *data, - int id, size_t *reqDataLen) -{ - int res; - u8 *req; - - res = eap_tls_buildReq_helper(sm, &data->ssl, EAP_TYPE_PEAP, - data->peap_version, id, &req, - reqDataLen); - - if (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); - } - - if (res == 1) - return eap_tls_build_ack(reqDataLen, id, EAP_TYPE_PEAP, - data->peap_version); - return req; -} - - -static u8 * eap_peap_encrypt(struct eap_sm *sm, struct eap_peap_data *data, - int id, u8 *plain, size_t plain_len, - size_t *out_len) -{ - int res; - u8 *pos; - struct eap_hdr *req; - - /* TODO: add support for fragmentation, if needed. This will need to - * add TLS Message Length field, if the frame is fragmented. */ - req = malloc(sizeof(struct eap_hdr) + 2 + data->ssl.tls_out_limit); - if (req == NULL) - return NULL; - - req->code = EAP_CODE_REQUEST; - req->identifier = id; - - pos = (u8 *) (req + 1); - *pos++ = EAP_TYPE_PEAP; - *pos++ = data->peap_version; - - res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn, - plain, plain_len, - pos, data->ssl.tls_out_limit); - if (res < 0) { - wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt Phase 2 " - "data"); - free(req); - return NULL; - } - - *out_len = sizeof(struct eap_hdr) + 2 + res; - req->length = host_to_be16(*out_len); - return (u8 *) req; -} - - -static u8 * eap_peap_build_phase2_req(struct eap_sm *sm, - struct eap_peap_data *data, - int id, size_t *reqDataLen) -{ - u8 *req, *buf, *encr_req; - size_t req_len; - - buf = req = data->phase2_method->buildReq(sm, data->phase2_priv, id, - &req_len); - if (req == NULL) - return NULL; - - 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); - } - - encr_req = eap_peap_encrypt(sm, data, id, req, req_len, reqDataLen); - free(buf); - - return encr_req; -} - - -static u8 * eap_peap_build_phase2_term(struct eap_sm *sm, - struct eap_peap_data *data, - int id, size_t *reqDataLen, int success) -{ - u8 *encr_req; - size_t req_len; - struct eap_hdr *hdr; - - req_len = sizeof(*hdr); - hdr = wpa_zalloc(req_len); - if (hdr == NULL) - return NULL; - - hdr->code = success ? EAP_CODE_SUCCESS : EAP_CODE_FAILURE; - hdr->identifier = id; - hdr->length = htons(req_len); - - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data", - (u8 *) hdr, req_len); - - encr_req = eap_peap_encrypt(sm, data, id, (u8 *) hdr, req_len, - reqDataLen); - free(hdr); - - return encr_req; -} - - -static u8 * eap_peap_buildReq(struct eap_sm *sm, void *priv, int id, - size_t *reqDataLen) -{ - struct eap_peap_data *data = priv; - - switch (data->state) { - case START: - return eap_peap_build_start(sm, data, id, reqDataLen); - case PHASE1: - return eap_peap_build_req(sm, data, id, reqDataLen); - case PHASE2_ID: - case PHASE2_METHOD: - case PHASE2_TLV: - return eap_peap_build_phase2_req(sm, data, id, reqDataLen); - case SUCCESS_REQ: - return eap_peap_build_phase2_term(sm, data, id, reqDataLen, 1); - case FAILURE_REQ: - return eap_peap_build_phase2_term(sm, data, id, reqDataLen, 0); - default: - wpa_printf(MSG_DEBUG, "EAP-PEAP: %s - unexpected state %d", - __func__, data->state); - return NULL; - } -} - - -static Boolean eap_peap_check(struct eap_sm *sm, void *priv, - u8 *respData, size_t respDataLen) -{ - struct eap_hdr *resp; - u8 *pos; - - resp = (struct eap_hdr *) respData; - pos = (u8 *) (resp + 1); - if (respDataLen < sizeof(*resp) + 2 || *pos != EAP_TYPE_PEAP || - (ntohs(resp->length)) > respDataLen) { - 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_sm_get_eap_methods(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 void eap_peap_process_phase2_response(struct eap_sm *sm, - struct eap_peap_data *data, - u8 *in_data, size_t in_len) -{ - u8 next_type = EAP_TYPE_NONE; - struct eap_hdr *hdr; - u8 *pos; - size_t left; - - if (data->phase2_priv == NULL) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: %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-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 { - next_type = eap_peap_req_failure(sm, data); - } - eap_peap_phase2_init(sm, data, next_type); - return; - } - - if (data->phase2_method->check(sm, data->phase2_priv, in_data, - in_len)) { - wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase2 check() asked to " - "ignore the packet"); - return; - } - - data->phase2_method->process(sm, data->phase2_priv, in_data, in_len); - - 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"); - next_type = eap_peap_req_failure(sm, data); - eap_peap_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_PEAP: Phase2 " - "Identity not found in the user " - "database", - sm->identity, sm->identity_len); - next_type = eap_peap_req_failure(sm, data); - break; - } - - 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: - next_type = eap_peap_req_success(sm, data); - break; - case PHASE2_TLV: - if (sm->tlv_request == TLV_REQ_SUCCESS || - data->state == SUCCESS_REQ) { - eap_peap_state(data, SUCCESS); - } else { - eap_peap_state(data, FAILURE); - } - 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, - struct eap_hdr *resp, - u8 *in_data, size_t in_len) -{ - u8 *in_decrypted; - int len_decrypted, len, res; - struct eap_hdr *hdr; - size_t buf_len; - - wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for" - " Phase 2", (unsigned long) in_len); - - res = eap_tls_data_reassemble(sm, &data->ssl, &in_data, &in_len); - if (res < 0 || res == 1) - return; - - buf_len = in_len; - if (data->ssl.tls_in_total > buf_len) - buf_len = data->ssl.tls_in_total; - in_decrypted = malloc(buf_len); - if (in_decrypted == NULL) { - free(data->ssl.tls_in); - data->ssl.tls_in = NULL; - data->ssl.tls_in_len = 0; - wpa_printf(MSG_WARNING, "EAP-PEAP: failed to allocate memory " - "for decryption"); - return; - } - - len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn, - in_data, in_len, - in_decrypted, buf_len); - free(data->ssl.tls_in); - data->ssl.tls_in = NULL; - data->ssl.tls_in_len = 0; - if (len_decrypted < 0) { - wpa_printf(MSG_INFO, "EAP-PEAP: Failed to decrypt Phase 2 " - "data"); - free(in_decrypted); - eap_peap_state(data, FAILURE); - return; - } - - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP", - in_decrypted, len_decrypted); - - hdr = (struct eap_hdr *) in_decrypted; - - if (data->peap_version == 0 && data->state != PHASE2_TLV) { - struct eap_hdr *nhdr = malloc(sizeof(struct eap_hdr) + - len_decrypted); - if (nhdr == NULL) { - free(in_decrypted); - return; - } - memcpy((u8 *) (nhdr + 1), in_decrypted, len_decrypted); - free(in_decrypted); - nhdr->code = resp->code; - nhdr->identifier = resp->identifier; - nhdr->length = host_to_be16(sizeof(struct eap_hdr) + - len_decrypted); - - len_decrypted += sizeof(struct eap_hdr); - in_decrypted = (u8 *) nhdr; - } - hdr = (struct eap_hdr *) in_decrypted; - if (len_decrypted < (int) sizeof(*hdr)) { - free(in_decrypted); - wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 " - "EAP frame (len=%d)", len_decrypted); - eap_peap_req_failure(sm, data); - return; - } - len = be_to_host16(hdr->length); - if (len > len_decrypted) { - free(in_decrypted); - wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in " - "Phase 2 EAP frame (len=%d hdr->length=%d)", - len_decrypted, len); - eap_peap_req_failure(sm, data); - return; - } - wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d " - "identifier=%d length=%d", hdr->code, hdr->identifier, len); - switch (hdr->code) { - case EAP_CODE_RESPONSE: - eap_peap_process_phase2_response(sm, data, (u8 *) hdr, len); - 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; - } - - free(in_decrypted); - } - - -static void eap_peap_process(struct eap_sm *sm, void *priv, - u8 *respData, size_t respDataLen) -{ - struct eap_peap_data *data = priv; - struct eap_hdr *resp; - u8 *pos, flags; - int left; - unsigned int tls_msg_len; - int peer_version; - - resp = (struct eap_hdr *) respData; - pos = (u8 *) (resp + 1); - pos++; - flags = *pos++; - left = htons(resp->length) - sizeof(struct eap_hdr) - 2; - wpa_printf(MSG_DEBUG, "EAP-PEAP: Received packet(len=%lu) - " - "Flags 0x%02x", (unsigned long) respDataLen, flags); - peer_version = flags & EAP_PEAP_VERSION_MASK; - 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); - eap_peap_state(data, FAILURE); - return; - } - 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; - } - if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) { - if (left < 4) { - wpa_printf(MSG_INFO, "EAP-PEAP: Short frame with TLS " - "length"); - eap_peap_state(data, FAILURE); - return; - } - tls_msg_len = (pos[0] << 24) | (pos[1] << 16) | (pos[2] << 8) | - pos[3]; - wpa_printf(MSG_DEBUG, "EAP-PEAP: TLS Message Length: %d", - tls_msg_len); - if (data->ssl.tls_in_left == 0) { - data->ssl.tls_in_total = tls_msg_len; - data->ssl.tls_in_left = tls_msg_len; - free(data->ssl.tls_in); - data->ssl.tls_in = NULL; - data->ssl.tls_in_len = 0; - } - pos += 4; - left -= 4; - } - - switch (data->state) { - case PHASE1: - if (eap_tls_process_helper(sm, &data->ssl, pos, left) < 0) { - wpa_printf(MSG_INFO, "EAP-PEAP: TLS processing " - "failed"); - eap_peap_state(data, FAILURE); - } - break; - case PHASE2_START: - eap_peap_state(data, PHASE2_ID); - eap_peap_phase2_init(sm, data, EAP_TYPE_IDENTITY); - break; - case PHASE2_ID: - case PHASE2_METHOD: - case PHASE2_TLV: - eap_peap_process_phase2(sm, data, resp, pos, left); - 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; - } - - if (tls_connection_get_write_alerts(sm->ssl_ctx, data->ssl.conn) > 1) { - wpa_printf(MSG_INFO, "EAP-PEAP: Locally detected fatal error " - "in TLS processing"); - 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; - - /* TODO: PEAPv1 - different label in some cases */ - eapKeyData = eap_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/contrib/hostapd/eap_psk.c b/contrib/hostapd/eap_psk.c deleted file mode 100644 index 7408a522e328..000000000000 --- a/contrib/hostapd/eap_psk.c +++ /dev/null @@ -1,494 +0,0 @@ -/* - * hostapd / EAP-PSK (RFC 4764) server - * Copyright (c) 2005-2007, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "hostapd.h" -#include "common.h" -#include "eap_i.h" -#include "aes_wrap.h" -#include "eap_psk_common.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 = wpa_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; - free(data->id_p); - free(data); -} - - -static u8 * eap_psk_build_1(struct eap_sm *sm, struct eap_psk_data *data, - int id, size_t *reqDataLen) -{ - struct eap_psk_hdr_1 *req; - - wpa_printf(MSG_DEBUG, "EAP-PSK: PSK-1 (sending)"); - - if (hostapd_get_rand(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); - - *reqDataLen = sizeof(*req) + data->id_s_len; - req = malloc(*reqDataLen); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory " - "request"); - data->state = FAILURE; - return NULL; - } - - req->code = EAP_CODE_REQUEST; - req->identifier = id; - req->length = htons(*reqDataLen); - req->type = EAP_TYPE_PSK; - req->flags = EAP_PSK_FLAGS_SET_T(0); /* T=0 */ - memcpy(req->rand_s, data->rand_s, EAP_PSK_RAND_LEN); - memcpy((u8 *) (req + 1), data->id_s, data->id_s_len); - - return (u8 *) req; -} - - -static u8 * eap_psk_build_3(struct eap_sm *sm, struct eap_psk_data *data, - int id, size_t *reqDataLen) -{ - struct eap_psk_hdr_3 *req; - u8 *buf, *pchannel, nonce[16]; - size_t buflen; - - wpa_printf(MSG_DEBUG, "EAP-PSK: PSK-3 (sending)"); - - *reqDataLen = sizeof(*req) + 4 + 16 + 1; - req = malloc(*reqDataLen); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory " - "request"); - data->state = FAILURE; - return NULL; - } - - req->code = EAP_CODE_REQUEST; - req->identifier = id; - req->length = htons(*reqDataLen); - req->type = EAP_TYPE_PSK; - req->flags = EAP_PSK_FLAGS_SET_T(2); /* T=2 */ - memcpy(req->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 = malloc(buflen); - if (buf == NULL) { - free(req); - data->state = FAILURE; - return NULL; - } - memcpy(buf, data->id_s, data->id_s_len); - memcpy(buf + data->id_s_len, data->rand_p, EAP_PSK_RAND_LEN); - omac1_aes_128(data->ak, buf, buflen, req->mac_s); - free(buf); - - eap_psk_derive_keys(data->kdk, data->rand_p, data->tek, data->msk, - data->emsk); - 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); - - memset(nonce, 0, sizeof(nonce)); - pchannel = (u8 *) (req + 1); - memcpy(pchannel, nonce + 12, 4); - 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); - aes_128_eax_encrypt(data->tek, nonce, sizeof(nonce), (u8 *) req, 22, - pchannel + 4 + 16, 1, pchannel + 4); - wpa_hexdump(MSG_DEBUG, "EAP-PSK: PCHANNEL (encrypted)", - pchannel, 4 + 16 + 1); - - return (u8 *) req; -} - - -static u8 * eap_psk_buildReq(struct eap_sm *sm, void *priv, int id, - size_t *reqDataLen) -{ - struct eap_psk_data *data = priv; - - switch (data->state) { - case PSK_1: - return eap_psk_build_1(sm, data, id, reqDataLen); - case PSK_3: - return eap_psk_build_3(sm, data, id, reqDataLen); - 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, - u8 *respData, size_t respDataLen) -{ - struct eap_psk_data *data = priv; - struct eap_psk_hdr *resp; - size_t len; - u8 t; - - resp = (struct eap_psk_hdr *) respData; - if (respDataLen < sizeof(*resp) || resp->type != EAP_TYPE_PSK || - (len = ntohs(resp->length)) > respDataLen || - len < sizeof(*resp)) { - wpa_printf(MSG_INFO, "EAP-PSK: Invalid frame"); - return TRUE; - } - t = EAP_PSK_FLAGS_GET_T(resp->flags); - - 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, - u8 *respData, size_t respDataLen) -{ - struct eap_psk_hdr_2 *resp; - u8 *pos, mac[EAP_PSK_MAC_LEN], *buf; - size_t len, left, buflen; - int i; - - if (data->state != PSK_1) - return; - - wpa_printf(MSG_DEBUG, "EAP-PSK: Received PSK-2"); - - resp = (struct eap_psk_hdr_2 *) respData; - len = ntohs(resp->length); - pos = (u8 *) (resp + 1); - left = len - sizeof(*resp); - - free(data->id_p); - data->id_p = malloc(left); - if (data->id_p == NULL) { - wpa_printf(MSG_INFO, "EAP-PSK: Failed to allocate memory for " - "ID_P"); - return; - } - memcpy(data->id_p, pos, 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; - } - eap_psk_key_setup(sm->user->password, data->ak, data->kdk); - 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); - 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 = malloc(buflen); - if (buf == NULL) { - data->state = FAILURE; - return; - } - memcpy(buf, data->id_p, data->id_p_len); - pos = buf + data->id_p_len; - memcpy(pos, data->id_s, data->id_s_len); - pos += data->id_s_len; - memcpy(pos, data->rand_s, EAP_PSK_RAND_LEN); - pos += EAP_PSK_RAND_LEN; - memcpy(pos, data->rand_p, EAP_PSK_RAND_LEN); - omac1_aes_128(data->ak, buf, buflen, mac); - free(buf); - wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_P", resp->mac_p, EAP_PSK_MAC_LEN); - if (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, - u8 *respData, size_t respDataLen) -{ - struct eap_psk_hdr_4 *resp; - u8 *pos, *decrypted, nonce[16], *tag; - size_t left; - - if (data->state != PSK_3) - return; - - wpa_printf(MSG_DEBUG, "EAP-PSK: Received PSK-4"); - - resp = (struct eap_psk_hdr_4 *) respData; - pos = (u8 *) (resp + 1); - left = ntohs(resp->length) - 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; - } - - memset(nonce, 0, 12); - memcpy(nonce + 12, pos, 4); - pos += 4; - left -= 4; - tag = pos; - pos += 16; - left -= 16; - - decrypted = malloc(left); - if (decrypted == NULL) - return; - memcpy(decrypted, pos, left); - - if (aes_128_eax_decrypt(data->tek, nonce, sizeof(nonce), - respData, 22, decrypted, left, tag)) { - wpa_printf(MSG_WARNING, "EAP-PSK: PCHANNEL decryption failed"); - 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; - } - free(decrypted); -} - - -static void eap_psk_process(struct eap_sm *sm, void *priv, - u8 *respData, size_t respDataLen) -{ - struct eap_psk_data *data = priv; - struct eap_psk_hdr *resp; - - if (sm->user == NULL || sm->user->password == NULL) { - wpa_printf(MSG_INFO, "EAP-PSK: Plaintext password not " - "configured"); - data->state = FAILURE; - return; - } - - resp = (struct eap_psk_hdr *) respData; - - switch (EAP_PSK_FLAGS_GET_T(resp->flags)) { - case 1: - eap_psk_process_2(sm, data, respData, respDataLen); - break; - case 3: - eap_psk_process_4(sm, data, respData, respDataLen); - 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 = malloc(EAP_MSK_LEN); - if (key == NULL) - return NULL; - 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 = malloc(EAP_EMSK_LEN); - if (key == NULL) - return NULL; - 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/contrib/hostapd/eap_psk_common.c b/contrib/hostapd/eap_psk_common.c deleted file mode 100644 index 8d896ae639d5..000000000000 --- a/contrib/hostapd/eap_psk_common.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * EAP server/peer: EAP-PSK shared routines - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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_wrap.h" -#include "eap_defs.h" -#include "eap_psk_common.h" - -#define aes_block_size 16 - - -void eap_psk_key_setup(const u8 *psk, u8 *ak, u8 *kdk) -{ - os_memset(ak, 0, aes_block_size); - aes_128_encrypt_block(psk, ak, ak); - os_memcpy(kdk, ak, aes_block_size); - ak[aes_block_size - 1] ^= 0x01; - kdk[aes_block_size - 1] ^= 0x02; - aes_128_encrypt_block(psk, ak, ak); - aes_128_encrypt_block(psk, kdk, kdk); -} - - -void 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; - - aes_128_encrypt_block(kdk, rand_p, hash); - - hash[aes_block_size - 1] ^= counter; - aes_128_encrypt_block(kdk, hash, tek); - hash[aes_block_size - 1] ^= counter; - counter++; - - for (i = 0; i < EAP_MSK_LEN / aes_block_size; i++) { - hash[aes_block_size - 1] ^= counter; - aes_128_encrypt_block(kdk, hash, &msk[i * aes_block_size]); - hash[aes_block_size - 1] ^= counter; - counter++; - } - - for (i = 0; i < EAP_EMSK_LEN / aes_block_size; i++) { - hash[aes_block_size - 1] ^= counter; - aes_128_encrypt_block(kdk, hash, &emsk[i * aes_block_size]); - hash[aes_block_size - 1] ^= counter; - counter++; - } -} diff --git a/contrib/hostapd/eap_psk_common.h b/contrib/hostapd/eap_psk_common.h deleted file mode 100644 index e1bdccf5916a..000000000000 --- a/contrib/hostapd/eap_psk_common.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * EAP server/peer: EAP-PSK shared routines - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 */ - -/* Shared prefix for all EAP-PSK frames */ -struct eap_psk_hdr { - u8 code; - u8 identifier; - u16 length; /* including code, identifier, and length */ - u8 type; /* EAP_TYPE_PSK */ - u8 flags; -} STRUCT_PACKED; - -/* EAP-PSK First Message (AS -> Supplicant) */ -struct eap_psk_hdr_1 { - u8 code; - u8 identifier; - u16 length; /* including code, identifier, and length */ - u8 type; /* EAP_TYPE_PSK */ - 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 code; - u8 identifier; - u16 length; /* including code, identifier, and length */ - u8 type; /* EAP_TYPE_PSK */ - 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 code; - u8 identifier; - u16 length; /* including code, identifier, and length */ - u8 type; /* EAP_TYPE_PSK */ - 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 code; - u8 identifier; - u16 length; /* including code, identifier, and length */ - u8 type; /* EAP_TYPE_PSK */ - 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 */ - - -void eap_psk_key_setup(const u8 *psk, u8 *ak, u8 *kdk); -void 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/contrib/hostapd/eap_sake.c b/contrib/hostapd/eap_sake.c deleted file mode 100644 index e031f29fb436..000000000000 --- a/contrib/hostapd/eap_sake.c +++ /dev/null @@ -1,547 +0,0 @@ -/* - * hostapd / EAP-SAKE (RFC 4763) server - * Copyright (c) 2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "hostapd.h" -#include "common.h" -#include "eap_i.h" -#include "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 = wpa_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = CHALLENGE; - - if (hostapd_get_rand(&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 *) strdup("hostapd"); - if (data->serverid) - data->serverid_len = 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 u8 * eap_sake_build_msg(struct eap_sake_data *data, u8 **payload, - int id, size_t *length, u8 subtype) -{ - struct eap_sake_hdr *req; - u8 *msg; - - *length += sizeof(struct eap_sake_hdr); - - msg = wpa_zalloc(*length); - if (msg == NULL) { - wpa_printf(MSG_ERROR, "EAP-SAKE: Failed to allocate memory " - "request"); - return NULL; - } - - req = (struct eap_sake_hdr *) msg; - req->code = EAP_CODE_REQUEST; - req->identifier = id; - req->length = htons((u16) *length); - req->type = EAP_TYPE_SAKE; - req->version = EAP_SAKE_VERSION; - req->session_id = data->session_id; - req->subtype = subtype; - *payload = (u8 *) (req + 1); - - return msg; -} - - -static u8 * eap_sake_build_identity(struct eap_sm *sm, - struct eap_sake_data *data, - int id, size_t *reqDataLen) -{ - u8 *msg, *pos; - - wpa_printf(MSG_DEBUG, "EAP-SAKE: Request/Identity"); - - *reqDataLen = 4; - if (data->serverid) - *reqDataLen += 2 + data->serverid_len; - msg = eap_sake_build_msg(data, &pos, id, reqDataLen, - EAP_SAKE_SUBTYPE_IDENTITY); - if (msg == NULL) { - data->state = FAILURE; - return NULL; - } - - wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_PERM_ID_REQ"); - *pos++ = EAP_SAKE_AT_PERM_ID_REQ; - *pos++ = 4; - *pos++ = 0; - *pos++ = 0; - - if (data->serverid) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_SERVERID"); - *pos++ = EAP_SAKE_AT_SERVERID; - *pos++ = 2 + data->serverid_len; - os_memcpy(pos, data->serverid, data->serverid_len); - } - - return msg; -} - - -static u8 * eap_sake_build_challenge(struct eap_sm *sm, - struct eap_sake_data *data, - int id, size_t *reqDataLen) -{ - u8 *msg, *pos; - - wpa_printf(MSG_DEBUG, "EAP-SAKE: Request/Challenge"); - - if (hostapd_get_rand(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); - - *reqDataLen = 2 + EAP_SAKE_RAND_LEN; - if (data->serverid) - *reqDataLen += 2 + data->serverid_len; - msg = eap_sake_build_msg(data, &pos, id, reqDataLen, - EAP_SAKE_SUBTYPE_CHALLENGE); - if (msg == NULL) { - data->state = FAILURE; - return NULL; - } - - wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_RAND_S"); - *pos++ = EAP_SAKE_AT_RAND_S; - *pos++ = 2 + EAP_SAKE_RAND_LEN; - os_memcpy(pos, data->rand_s, EAP_SAKE_RAND_LEN); - pos += EAP_SAKE_RAND_LEN; - - if (data->serverid) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_SERVERID"); - *pos++ = EAP_SAKE_AT_SERVERID; - *pos++ = 2 + data->serverid_len; - os_memcpy(pos, data->serverid, data->serverid_len); - } - - return msg; -} - - -static u8 * eap_sake_build_confirm(struct eap_sm *sm, - struct eap_sake_data *data, - int id, size_t *reqDataLen) -{ - u8 *msg, *pos; - - wpa_printf(MSG_DEBUG, "EAP-SAKE: Request/Confirm"); - - *reqDataLen = 2 + EAP_SAKE_MIC_LEN; - msg = eap_sake_build_msg(data, &pos, id, reqDataLen, - EAP_SAKE_SUBTYPE_CONFIRM); - if (msg == NULL) { - data->state = FAILURE; - return NULL; - } - - wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_MIC_S"); - *pos++ = EAP_SAKE_AT_MIC_S; - *pos++ = 2 + 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, - msg, *reqDataLen, pos, pos)) { - wpa_printf(MSG_INFO, "EAP-SAKE: Failed to compute MIC"); - data->state = FAILURE; - os_free(msg); - return NULL; - } - - return msg; -} - - -static u8 * eap_sake_buildReq(struct eap_sm *sm, void *priv, int id, - size_t *reqDataLen) -{ - struct eap_sake_data *data = priv; - - switch (data->state) { - case IDENTITY: - return eap_sake_build_identity(sm, data, id, reqDataLen); - case CHALLENGE: - return eap_sake_build_challenge(sm, data, id, reqDataLen); - case CONFIRM: - return eap_sake_build_confirm(sm, data, id, reqDataLen); - 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, - u8 *respData, size_t respDataLen) -{ - struct eap_sake_data *data = priv; - struct eap_sake_hdr *resp; - size_t len; - u8 version, session_id, subtype; - - resp = (struct eap_sake_hdr *) respData; - if (respDataLen < sizeof(*resp) || - resp->type != EAP_TYPE_SAKE || - (len = ntohs(resp->length)) > respDataLen || - len < sizeof(*resp)) { - wpa_printf(MSG_INFO, "EAP-SAKE: Invalid frame"); - return TRUE; - } - 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, - u8 *respData, size_t respDataLen, - 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, - u8 *respData, size_t respDataLen, - 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, - respData, respDataLen, 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, - u8 *respData, size_t respDataLen, - 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, - respData, respDataLen, 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, - u8 *respData, size_t respDataLen, - 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, - u8 *respData, size_t respDataLen) -{ - struct eap_sake_data *data = priv; - struct eap_sake_hdr *resp; - u8 subtype, *pos, *end; - - resp = (struct eap_sake_hdr *) respData; - subtype = resp->subtype; - pos = (u8 *) (resp + 1); - end = respData + ntohs(resp->length); - - 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, respDataLen, pos, - end - pos); - break; - case EAP_SAKE_SUBTYPE_CHALLENGE: - eap_sake_process_challenge(sm, data, respData, respDataLen, - pos, end - pos); - break; - case EAP_SAKE_SUBTYPE_CONFIRM: - eap_sake_process_confirm(sm, data, respData, respDataLen, pos, - end - pos); - break; - case EAP_SAKE_SUBTYPE_AUTH_REJECT: - eap_sake_process_auth_reject(sm, data, respData, respDataLen, - 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/contrib/hostapd/eap_sake_common.c b/contrib/hostapd/eap_sake_common.c deleted file mode 100644 index 4b5476f101c8..000000000000 --- a/contrib/hostapd/eap_sake_common.c +++ /dev/null @@ -1,380 +0,0 @@ -/* - * EAP server/peer: EAP-SAKE shared routines - * Copyright (c) 2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "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; -} diff --git a/contrib/hostapd/eap_sake_common.h b/contrib/hostapd/eap_sake_common.h deleted file mode 100644 index ac6e8199d66b..000000000000 --- a/contrib/hostapd/eap_sake_common.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * EAP server/peer: EAP-SAKE shared routines - * Copyright (c) 2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 code; - u8 identifier; - u16 length; - u8 type; /* EAP_TYPE_SAKE */ - 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); - -#endif /* EAP_SAKE_COMMON_H */ diff --git a/contrib/hostapd/eap_sim.c b/contrib/hostapd/eap_sim.c deleted file mode 100644 index 3db24923d43f..000000000000 --- a/contrib/hostapd/eap_sim.c +++ /dev/null @@ -1,707 +0,0 @@ -/* - * hostapd / EAP-SIM (RFC 4186) - * Copyright (c) 2005-2008, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "hostapd.h" -#include "common.h" -#include "crypto.h" -#include "eap_i.h" -#include "eap_sim_common.h" -#include "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, SUCCESS, FAILURE } state; - char *next_pseudonym; - char *next_reauth_id; - u16 counter; - struct eap_sim_reauth *reauth; -}; - - -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"; - 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 = wpa_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; - free(data->next_pseudonym); - free(data->next_reauth_id); - free(data); -} - - -static u8 * eap_sim_build_start(struct eap_sm *sm, struct eap_sim_data *data, - int id, size_t *reqDataLen) -{ - 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, reqDataLen, 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) -{ - free(data->next_pseudonym); - data->next_pseudonym = - eap_sim_db_get_next_pseudonym(sm->eap_sim_db_priv, 0); - 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, - strlen(data->next_pseudonym), - (u8 *) data->next_pseudonym, - 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, - strlen(data->next_reauth_id), - (u8 *) data->next_reauth_id, - 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 u8 * eap_sim_build_challenge(struct eap_sm *sm, - struct eap_sim_data *data, - int id, size_t *reqDataLen) -{ - 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; - } - - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - return eap_sim_msg_finish(msg, reqDataLen, data->k_aut, data->nonce_mt, - EAP_SIM_NONCE_MT_LEN); -} - - -static u8 * eap_sim_build_reauth(struct eap_sm *sm, - struct eap_sim_data *data, - int id, size_t *reqDataLen) -{ - struct eap_sim_msg *msg; - - wpa_printf(MSG_DEBUG, "EAP-SIM: Generating Re-authentication"); - - if (hostapd_get_rand(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; - } - - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - return eap_sim_msg_finish(msg, reqDataLen, data->k_aut, NULL, 0); -} - - -static u8 * eap_sim_buildReq(struct eap_sm *sm, void *priv, int id, - size_t *reqDataLen) -{ - struct eap_sim_data *data = priv; - - switch (data->state) { - case START: - return eap_sim_build_start(sm, data, id, reqDataLen); - case CHALLENGE: - return eap_sim_build_challenge(sm, data, id, reqDataLen); - case REAUTH: - return eap_sim_build_reauth(sm, data, id, reqDataLen); - 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, - u8 *respData, size_t respDataLen) -{ - struct eap_sim_data *data = priv; - struct eap_hdr *resp; - u8 *pos, subtype; - - resp = (struct eap_hdr *) respData; - pos = (u8 *) (resp + 1); - if (respDataLen < sizeof(*resp) + 4 || *pos != EAP_TYPE_SIM || - (ntohs(resp->length)) > respDataLen) { - wpa_printf(MSG_INFO, "EAP-SIM: Invalid frame"); - return TRUE; - } - subtype = pos[1]; - - 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; - 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, - u8 *respData, size_t respDataLen, - 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) { - free(sm->identity); - sm->identity = malloc(attr->identity_len); - if (sm->identity) { - 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; - 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); - - 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, - u8 *respData, size_t respDataLen, - struct eap_sim_attrs *attr) -{ - const u8 *identity; - size_t identity_len; - - if (attr->mac == NULL || - eap_sim_verify_mac(data->k_aut, respData, respDataLen, 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"); - 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, - u8 *respData, size_t respDataLen, - 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, respDataLen, 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; - } - free(decrypted); - decrypted = NULL; - - wpa_printf(MSG_DEBUG, "EAP-SIM: Re-authentication response includes " - "the correct AT_MAC"); - 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; - free(decrypted); -} - - -static void eap_sim_process_client_error(struct eap_sm *sm, - struct eap_sim_data *data, - u8 *respData, size_t respDataLen, - struct eap_sim_attrs *attr) -{ - wpa_printf(MSG_DEBUG, "EAP-SIM: Client reported error %d", - attr->client_error_code); - eap_sim_state(data, FAILURE); -} - - -static void eap_sim_process(struct eap_sm *sm, void *priv, - u8 *respData, size_t respDataLen) -{ - struct eap_sim_data *data = priv; - struct eap_hdr *resp; - u8 *pos, subtype; - size_t len; - struct eap_sim_attrs attr; - - resp = (struct eap_hdr *) respData; - pos = (u8 *) (resp + 1); - subtype = pos[1]; - len = ntohs(resp->length); - pos += 4; - - if (eap_sim_parse_attr(pos, respData + len, &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, len, &attr); - return; - } - - switch (data->state) { - case START: - eap_sim_process_start(sm, data, respData, len, &attr); - break; - case CHALLENGE: - eap_sim_process_challenge(sm, data, respData, len, &attr); - break; - case REAUTH: - eap_sim_process_reauth(sm, data, respData, len, &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 = malloc(EAP_SIM_KEYING_DATA_LEN); - if (key == NULL) - return NULL; - 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 = malloc(EAP_EMSK_LEN); - if (key == NULL) - return NULL; - 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/contrib/hostapd/eap_sim_common.c b/contrib/hostapd/eap_sim_common.c deleted file mode 100644 index cc430239ab97..000000000000 --- a/contrib/hostapd/eap_sim_common.c +++ /dev/null @@ -1,849 +0,0 @@ -/* - * EAP peer: EAP-SIM/AKA shared routines - * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "sha1.h" -#include "crypto.h" -#include "aes_wrap.h" -#include "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 u8 *req, size_t req_len, - 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 || req_len < EAP_SIM_MAC_LEN || mac < req || - mac > req + req_len - EAP_SIM_MAC_LEN) - return -1; - - tmp = os_malloc(req_len); - if (tmp == NULL) - return -1; - - addr[0] = tmp; - len[0] = req_len; - addr[1] = extra; - len[1] = extra_len; - - /* HMAC-SHA1-128 */ - os_memcpy(tmp, req, req_len); - os_memset(tmp + (mac - req), 0, EAP_SIM_MAC_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Verify MAC - msg", tmp, req_len); - 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, 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); -} - - -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"); - attr->identity = apos + 2; - attr->identity_len = alen - 2; - 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"); - 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; - 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); - - aes_128_cbc_decrypt(k_encr, iv, decrypted, encr_data_len); - 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 { - u8 *buf; - size_t buf_len, used; - size_t mac, iv, encr; /* index from buf */ -}; - - -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->buf = os_zalloc(EAP_SIM_INIT_LEN); - if (msg->buf == NULL) { - os_free(msg); - return NULL; - } - msg->buf_len = EAP_SIM_INIT_LEN; - eap = (struct eap_hdr *) msg->buf; - eap->code = code; - eap->identifier = id; - msg->used = sizeof(*eap); - - pos = (u8 *) (eap + 1); - *pos++ = type; - *pos++ = subtype; - *pos++ = 0; /* Reserved */ - *pos++ = 0; /* Reserved */ - msg->used += 4; - - return msg; -} - - -u8 * eap_sim_msg_finish(struct eap_sim_msg *msg, size_t *len, const u8 *k_aut, - const u8 *extra, size_t extra_len) -{ - struct eap_hdr *eap; - u8 *buf; - - if (msg == NULL) - return NULL; - - eap = (struct eap_hdr *) msg->buf; - eap->length = host_to_be16(msg->used); - - if (k_aut && msg->mac) { - eap_sim_add_mac(k_aut, msg->buf, msg->used, - msg->buf + msg->mac, extra, extra_len); - } - - *len = msg->used; - buf = msg->buf; - os_free(msg); - return buf; -} - - -void eap_sim_msg_free(struct eap_sim_msg *msg) -{ - if (msg) { - os_free(msg->buf); - os_free(msg); - } -} - - -static int eap_sim_msg_resize(struct eap_sim_msg *msg, size_t add_len) -{ - if (msg->used + add_len > msg->buf_len) { - u8 *nbuf = os_realloc(msg->buf, msg->used + add_len); - if (nbuf == NULL) - return -1; - msg->buf = nbuf; - msg->buf_len = msg->used + add_len; - } - return 0; -} - - -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, *pos; - - if (msg == NULL) - return NULL; - - pad_len = (4 - attr_len % 4) % 4; - attr_len += pad_len; - if (eap_sim_msg_resize(msg, attr_len)) - return NULL; - start = pos = msg->buf + msg->used; - *pos++ = attr; - *pos++ = attr_len / 4; - os_memcpy(pos, data, len); - if (pad_len) { - pos += len; - os_memset(pos, 0, pad_len); - } - msg->used += attr_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, *pos; - - if (msg == NULL) - return NULL; - - pad_len = (4 - attr_len % 4) % 4; - attr_len += pad_len; - if (eap_sim_msg_resize(msg, attr_len)) - return NULL; - start = pos = msg->buf + msg->used; - *pos++ = attr; - *pos++ = attr_len / 4; - WPA_PUT_BE16(pos, value); - pos += 2; - if (data) - os_memcpy(pos, data, len); - if (pad_len) { - pos += len; - os_memset(pos, 0, pad_len); - } - msg->used += attr_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 - 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 - msg->buf) + 4; - if (hostapd_get_rand(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 - 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 = msg->used - 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); - msg->buf[msg->encr + 1] = encr_len / 4 + 1; - aes_128_cbc_encrypt(k_encr, msg->buf + msg->iv, - msg->buf + msg->encr + 4, encr_len); - - return 0; -} - - -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/contrib/hostapd/eap_sim_common.h b/contrib/hostapd/eap_sim_common.h deleted file mode 100644 index 9c983a864e3e..000000000000 --- a/contrib/hostapd/eap_sim_common.h +++ /dev/null @@ -1,166 +0,0 @@ -/* - * EAP peer: EAP-SIM/AKA shared routines - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 - -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 u8 *req, size_t req_len, - const u8 *mac, const u8 *extra, size_t extra_len); -void eap_sim_add_mac(const u8 *k_aut, u8 *msg, size_t msg_len, u8 *mac, - const u8 *extra, size_t extra_len); - - -/* 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_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 - -/* 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 - - -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; - size_t num_chal, version_list_len, encr_data_len; - size_t next_pseudonym_len, next_reauth_id_len, identity_len, res_len; - enum eap_sim_id_req id_req; - int notification, counter, selected_version, client_error_code; - int counter_too_small; -}; - -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); -u8 * eap_sim_msg_finish(struct eap_sim_msg *msg, size_t *len, 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/contrib/hostapd/eap_sim_db.c b/contrib/hostapd/eap_sim_db.c deleted file mode 100644 index 59c11ac15142..000000000000 --- a/contrib/hostapd/eap_sim_db.c +++ /dev/null @@ -1,1275 +0,0 @@ -/* - * hostapd / EAP-SIM database/authenticator gateway - * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 <sys/un.h> - -#include "common.h" -#include "eap_sim_common.h" -#include "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 && - 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 <IMSI> Kc(i):SRES(i):RAND(i) ... - * SIM-RESP-AUTH <IMSI> FAILURE - * (IMSI = ASCII string, Kc/SRES/RAND = hex string) - */ - - entry = eap_sim_db_get_pending(data, (u8 *) imsi, 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 (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 = strchr(start, ' '); - if (end) - *end = '\0'; - - pos = 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 = 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"); - 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 <IMSI> <RAND> <AUTN> <IK> <CK> <RES> - * AKA-RESP-AUTH <IMSI> FAILURE - * (IMSI = ASCII string, RAND/AUTN/IK/CK/RES = hex string) - */ - - entry = eap_sim_db_get_pending(data, (u8 *) imsi, 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 (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 = 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 = 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 = 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 = 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 = 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"); - 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> <IMSI> ... */ - - cmd = buf; - pos = strchr(cmd, ' '); - if (pos == NULL) - goto parse_fail; - *pos = '\0'; - imsi = pos + 1; - pos = 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 (strcmp(cmd, "SIM-RESP-AUTH") == 0) - eap_sim_db_sim_resp_auth(data, imsi, pos + 1); - else if (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 (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; - } - - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - snprintf(addr.sun_path, sizeof(addr.sun_path), - "/tmp/eap_sim_db_%d-%d", getpid(), counter++); - data->local_sock = 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; - } - - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", data->fname + 5); - 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, 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); - 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 = wpa_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - - data->sock = -1; - data->get_complete_cb = get_complete_cb; - data->ctx = ctx; - data->fname = strdup(config); - if (data->fname == NULL) - goto fail; - - if (strncmp(data->fname, "unix:", 5) == 0) { - if (eap_sim_db_open_socket(data)) - goto fail; - } - - return data; - -fail: - eap_sim_db_close_socket(data); - free(data->fname); - free(data); - return NULL; -} - - -static void eap_sim_db_free_pseudonym(struct eap_sim_pseudonym *p) -{ - free(p->identity); - free(p->pseudonym); - free(p); -} - - -static void eap_sim_db_free_reauth(struct eap_sim_reauth *r) -{ - free(r->identity); - free(r->reauth_id); - 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); - 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; - free(prev_pending); - } - - 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"); - 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; - memcpy(_rand, entry->u.sim.rand, num_chal * GSM_RAND_LEN); - memcpy(sres, entry->u.sim.sres, num_chal * EAP_SIM_SRES_LEN); - memcpy(kc, entry->u.sim.kc, num_chal * EAP_SIM_KC_LEN); - free(entry); - return num_chal; - } - - if (data->sock < 0) { - if (eap_sim_db_open_socket(data) < 0) - return EAP_SIM_DB_FAILURE; - } - - len = snprintf(msg, sizeof(msg), "SIM-REQ-AUTH "); - if (len < 0 || len + identity_len >= sizeof(msg)) - return EAP_SIM_DB_FAILURE; - memcpy(msg + len, identity, identity_len); - len += identity_len; - ret = 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 = wpa_zalloc(sizeof(*entry)); - if (entry == NULL) - return EAP_SIM_DB_FAILURE; - - os_get_time(&entry->timestamp); - 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 = malloc(len + 1); - if (pseudonym == NULL) - return NULL; - memcpy(pseudonym, identity, len); - pseudonym[len] = '\0'; - - p = data->pseudonyms; - while (p) { - if (strcmp(p->pseudonym, pseudonym) == 0) - break; - p = p->next; - } - - 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 && - 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 = malloc(len + 1); - if (reauth_id == NULL) - return NULL; - memcpy(reauth_id, identity, len); - reauth_id[len] = '\0'; - - r = data->reauths; - while (r) { - if (strcmp(r->reauth_id, reauth_id) == 0) - break; - r = r->next; - } - - 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 && - 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 (hostapd_get_rand(buf, sizeof(buf))) - return NULL; - id = 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); - free(p->pseudonym); - p->pseudonym = pseudonym; - return 0; - } - - p = wpa_zalloc(sizeof(*p)); - if (p == NULL) { - free(pseudonym); - return -1; - } - - p->next = data->pseudonyms; - p->identity = malloc(identity_len); - if (p->identity == NULL) { - free(p); - free(pseudonym); - return -1; - } - 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; -} - - -/** - * 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. - * @mk: 16-byte MK from the previous full authentication - * 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; - 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); - free(r->reauth_id); - r->reauth_id = reauth_id; - } else { - r = wpa_zalloc(sizeof(*r)); - if (r == NULL) { - free(reauth_id); - return -1; - } - - r->next = data->reauths; - r->identity = malloc(identity_len); - if (r->identity == NULL) { - free(r); - free(reauth_id); - return -1; - } - 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; - memcpy(r->mk, mk, EAP_SIM_MK_LEN); - - return 0; -} - - -/** - * 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 - * @len: Buffer for length of the returned permanent 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) { - 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"); - memcpy(_rand, entry->u.aka.rand, EAP_AKA_RAND_LEN); - memcpy(autn, entry->u.aka.autn, EAP_AKA_AUTN_LEN); - memcpy(ik, entry->u.aka.ik, EAP_AKA_IK_LEN); - memcpy(ck, entry->u.aka.ck, EAP_AKA_CK_LEN); - memcpy(res, entry->u.aka.res, EAP_AKA_RES_MAX_LEN); - *res_len = entry->u.aka.res_len; - free(entry); - return 0; - } - - if (data->sock < 0) { - if (eap_sim_db_open_socket(data) < 0) - return EAP_SIM_DB_FAILURE; - } - - len = snprintf(msg, sizeof(msg), "AKA-REQ-AUTH "); - if (len < 0 || len + identity_len >= sizeof(msg)) - return EAP_SIM_DB_FAILURE; - 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 = wpa_zalloc(sizeof(*entry)); - if (entry == NULL) - return EAP_SIM_DB_FAILURE; - - os_get_time(&entry->timestamp); - entry->aka = 1; - 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 = snprintf(msg, sizeof(msg), "AKA-AUTS "); - if (len < 0 || len + identity_len >= sizeof(msg)) - return -1; - memcpy(msg + len, identity, identity_len); - len += identity_len; - - ret = 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 = 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/contrib/hostapd/eap_sim_db.h b/contrib/hostapd/eap_sim_db.h deleted file mode 100644 index 6754bc3d4ccd..000000000000 --- a/contrib/hostapd/eap_sim_db.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * hostapd / EAP-SIM database/authenticator gateway - * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 - -#ifdef EAP_SIM - -#include "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); - -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; - u8 mk[EAP_SIM_MK_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); - -#else /* EAP_SIM */ -static inline void * -eap_sim_db_init(const char *config, - void (*get_complete_cb)(void *ctx, void *session_ctx), - void *ctx) -{ - return (void *) 1; -} - -static inline void eap_sim_db_deinit(void *priv) -{ -} -#endif /* EAP_SIM */ - -#endif /* EAP_SIM_DB_H */ diff --git a/contrib/hostapd/eap_tls.c b/contrib/hostapd/eap_tls.c deleted file mode 100644 index fc85337d56d9..000000000000 --- a/contrib/hostapd/eap_tls.c +++ /dev/null @@ -1,292 +0,0 @@ -/* - * hostapd / EAP-TLS (RFC 2716) - * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "hostapd.h" -#include "common.h" -#include "eap_i.h" -#include "eap_tls_common.h" -#include "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; -}; - - -static void * eap_tls_init(struct eap_sm *sm) -{ - struct eap_tls_data *data; - - data = wpa_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = START; - - if (eap_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_tls_ssl_deinit(sm, &data->ssl); - free(data); -} - - -static u8 * eap_tls_build_start(struct eap_sm *sm, struct eap_tls_data *data, - int id, size_t *reqDataLen) -{ - struct eap_hdr *req; - u8 *pos; - - *reqDataLen = sizeof(*req) + 2; - req = malloc(*reqDataLen); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-TLS: Failed to allocate memory for " - "request"); - data->state = FAILURE; - return NULL; - } - - req->code = EAP_CODE_REQUEST; - req->identifier = id; - req->length = htons(*reqDataLen); - pos = (u8 *) (req + 1); - *pos++ = EAP_TYPE_TLS; - *pos = EAP_TLS_FLAGS_START; - - data->state = CONTINUE; - - return (u8 *) req; -} - - -static u8 * eap_tls_build_req(struct eap_sm *sm, struct eap_tls_data *data, - int id, size_t *reqDataLen) -{ - int res; - u8 *req; - - res = eap_tls_buildReq_helper(sm, &data->ssl, EAP_TYPE_TLS, 0, id, - &req, reqDataLen); - - if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { - wpa_printf(MSG_DEBUG, "EAP-TLS: Done"); - data->state = SUCCESS; - } - - if (res == 1) - return eap_tls_build_ack(reqDataLen, id, EAP_TYPE_TLS, 0); - return req; -} - - -static u8 * eap_tls_buildReq(struct eap_sm *sm, void *priv, int id, - size_t *reqDataLen) -{ - struct eap_tls_data *data = priv; - - switch (data->state) { - case START: - return eap_tls_build_start(sm, data, id, reqDataLen); - case CONTINUE: - return eap_tls_build_req(sm, data, id, reqDataLen); - default: - wpa_printf(MSG_DEBUG, "EAP-TLS: %s - unexpected state %d", - __func__, data->state); - return NULL; - } -} - - -static Boolean eap_tls_check(struct eap_sm *sm, void *priv, - u8 *respData, size_t respDataLen) -{ - struct eap_hdr *resp; - u8 *pos; - - resp = (struct eap_hdr *) respData; - pos = (u8 *) (resp + 1); - if (respDataLen < sizeof(*resp) + 2 || *pos != EAP_TYPE_TLS || - (ntohs(resp->length)) > respDataLen) { - wpa_printf(MSG_INFO, "EAP-TLS: Invalid frame"); - return TRUE; - } - - return FALSE; -} - - -static void eap_tls_process(struct eap_sm *sm, void *priv, - u8 *respData, size_t respDataLen) -{ - struct eap_tls_data *data = priv; - struct eap_hdr *resp; - u8 *pos, flags; - int left; - unsigned int tls_msg_len; - - resp = (struct eap_hdr *) respData; - pos = (u8 *) (resp + 1); - pos++; - flags = *pos++; - left = htons(resp->length) - sizeof(struct eap_hdr) - 2; - wpa_printf(MSG_DEBUG, "EAP-TLS: Received packet(len=%lu) - " - "Flags 0x%02x", (unsigned long) respDataLen, flags); - if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) { - if (left < 4) { - wpa_printf(MSG_INFO, "EAP-TLS: Short frame with TLS " - "length"); - data->state = FAILURE; - return; - } - tls_msg_len = (pos[0] << 24) | (pos[1] << 16) | (pos[2] << 8) | - pos[3]; - wpa_printf(MSG_DEBUG, "EAP-TLS: TLS Message Length: %d", - tls_msg_len); - if (data->ssl.tls_in_left == 0) { - data->ssl.tls_in_total = tls_msg_len; - data->ssl.tls_in_left = tls_msg_len; - free(data->ssl.tls_in); - data->ssl.tls_in = NULL; - data->ssl.tls_in_len = 0; - } - pos += 4; - left -= 4; - } - - if (eap_tls_process_helper(sm, &data->ssl, pos, left) < 0) { - wpa_printf(MSG_INFO, "EAP-TLS: TLS processing failed"); - data->state = FAILURE; - return; - } - - if (tls_connection_get_write_alerts(sm->ssl_ctx, data->ssl.conn) > 1) { - wpa_printf(MSG_INFO, "EAP-TLS: Locally detected fatal error " - "in TLS processing"); - data->state = FAILURE; - return; - } -} - - -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_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_tls_derive_key(sm, &data->ssl, - "client EAP encryption", - EAP_TLS_KEY_LEN + EAP_EMSK_LEN); - if (eapKeyData) { - emsk = malloc(EAP_EMSK_LEN); - if (emsk) - memcpy(emsk, eapKeyData + EAP_TLS_KEY_LEN, - EAP_EMSK_LEN); - 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/contrib/hostapd/eap_tls_common.c b/contrib/hostapd/eap_tls_common.c deleted file mode 100644 index ce61729bc944..000000000000 --- a/contrib/hostapd/eap_tls_common.c +++ /dev/null @@ -1,301 +0,0 @@ -/* - * hostapd / EAP-TLS/PEAP/TTLS common functions - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "hostapd.h" -#include "common.h" -#include "eap_i.h" -#include "eap_tls_common.h" -#include "sha1.h" -#include "tls.h" - - -int eap_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; - } - - /* TODO: make this configurable */ - data->tls_out_limit = 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_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data) -{ - tls_connection_deinit(sm->ssl_ctx, data->conn); - free(data->tls_in); - free(data->tls_out); -} - - -u8 * eap_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 = 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 = malloc(keys.client_random_len + keys.server_random_len); - if (rnd == NULL) - goto fail; - memcpy(rnd, keys.client_random, keys.client_random_len); - 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; - - free(rnd); - return out; - -fail: - free(out); - free(rnd); - return NULL; -} - - -int eap_tls_data_reassemble(struct eap_sm *sm, struct eap_ssl_data *data, - u8 **in_data, size_t *in_len) -{ - u8 *buf; - - if (data->tls_in_left > *in_len || data->tls_in) { - if (*in_len == 0) { - wpa_printf(MSG_INFO, "SSL: Empty fragment when trying " - "to reassemble"); - return -1; - } - if (data->tls_in_len + *in_len > 65536) { - /* Limit length to avoid rogue peers from causing large - * memory allocations. */ - free(data->tls_in); - data->tls_in = NULL; - data->tls_in_len = 0; - wpa_printf(MSG_INFO, "SSL: Too long TLS fragment (size" - " over 64 kB)"); - return -1; - } - buf = realloc(data->tls_in, data->tls_in_len + *in_len); - if (buf == NULL) { - free(data->tls_in); - data->tls_in = NULL; - data->tls_in_len = 0; - wpa_printf(MSG_INFO, "SSL: Could not allocate memory " - "for TLS data"); - return -1; - } - memcpy(buf + data->tls_in_len, *in_data, *in_len); - data->tls_in = buf; - data->tls_in_len += *in_len; - if (*in_len > data->tls_in_left) { - wpa_printf(MSG_INFO, "SSL: more data than TLS message " - "length indicated"); - data->tls_in_left = 0; - return -1; - } - 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; - } - - *in_data = data->tls_in; - *in_len = data->tls_in_len; - } else - data->tls_in_left = 0; - - return 0; -} - - -int eap_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data, - u8 *in_data, size_t in_len) -{ - WPA_ASSERT(data->tls_out_len == 0 || in_len == 0); - - if (data->tls_out_len == 0) { - /* No more data to send out - expect to receive more data from - * the peer. */ - int res = eap_tls_data_reassemble(sm, data, &in_data, &in_len); - if (res < 0 || res == 1) { - wpa_printf(MSG_DEBUG, "SSL: data reassembly failed"); - return res; - } - /* Full TLS message reassembled - continue handshake processing - */ - if (data->tls_out) { - /* This should not happen.. */ - wpa_printf(MSG_INFO, "SSL: eap_tls_process_helper - " - "pending tls_out data even though " - "tls_out_len = 0"); - free(data->tls_out); - WPA_ASSERT(data->tls_out == NULL); - } - data->tls_out = tls_connection_server_handshake( - sm->ssl_ctx, data->conn, in_data, in_len, - &data->tls_out_len); - - /* Clear reassembled input data (if the buffer was needed). */ - data->tls_in_left = data->tls_in_total = data->tls_in_len = 0; - free(data->tls_in); - data->tls_in = NULL; - } - - if (data->tls_out == NULL) { - wpa_printf(MSG_DEBUG, "SSL: failed to generate output data"); - data->tls_out_len = 0; - return -1; - } - if (data->tls_out_len == 0) { - /* TLS negotiation should now be complete since all other cases - * needing more that should have been catched above based on - * the TLS Message Length field. */ - wpa_printf(MSG_DEBUG, "SSL: No data to be sent out"); - free(data->tls_out); - data->tls_out = NULL; - - if (tls_connection_get_read_alerts(sm->ssl_ctx, data->conn)) { - wpa_printf(MSG_DEBUG, "SSL: Remote end sent a fatal " - "alert - abort handshake"); - return -1; - } - - return 1; - } - - wpa_printf(MSG_DEBUG, "SSL: %lu bytes left to be sent out (of total " - "%lu bytes)", - (unsigned long) data->tls_out_len - data->tls_out_pos, - (unsigned long) data->tls_out_len); - - return 0; -} - - -int eap_tls_buildReq_helper(struct eap_sm *sm, struct eap_ssl_data *data, - int eap_type, int peap_version, u8 id, - u8 **out_data, size_t *out_len) -{ - size_t len; - u8 *pos, *flags; - struct eap_hdr *req; - - *out_len = 0; - - req = malloc(sizeof(struct eap_hdr) + 2 + 4 + data->tls_out_limit); - if (req == NULL) { - *out_data = NULL; - return -1; - } - req->code = EAP_CODE_REQUEST; - req->identifier = id; - pos = (u8 *) (req + 1); - *pos++ = eap_type; - flags = pos++; - *flags = peap_version; - if (data->tls_out_pos == 0 && - data->tls_out_len > data->tls_out_limit) { - *flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED; - *pos++ = (data->tls_out_len >> 24) & 0xff; - *pos++ = (data->tls_out_len >> 16) & 0xff; - *pos++ = (data->tls_out_len >> 8) & 0xff; - *pos++ = data->tls_out_len & 0xff; - } - - len = data->tls_out_len - data->tls_out_pos; - if (len > data->tls_out_limit) { - *flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS; - len = data->tls_out_limit; - wpa_printf(MSG_DEBUG, "SSL: sending %lu bytes, more fragments " - "will follow", (unsigned long) len); - } - memcpy(pos, &data->tls_out[data->tls_out_pos], len); - data->tls_out_pos += len; - *out_len = (pos - (u8 *) req) + len; - req->length = htons(*out_len); - *out_data = (u8 *) req; - - if (!(*flags & EAP_TLS_FLAGS_MORE_FRAGMENTS)) { - data->tls_out_len = 0; - data->tls_out_pos = 0; - free(data->tls_out); - data->tls_out = NULL; - } - - return 0; -} - - -u8 * eap_tls_build_ack(size_t *reqDataLen, u8 id, int eap_type, - int peap_version) -{ - struct eap_hdr *req; - u8 *pos; - - *reqDataLen = sizeof(struct eap_hdr) + 2; - req = malloc(*reqDataLen); - if (req == NULL) - return NULL; - wpa_printf(MSG_DEBUG, "SSL: Building ACK"); - req->code = EAP_CODE_REQUEST; - req->identifier = id; - req->length = htons(*reqDataLen); - pos = (u8 *) (req + 1); - *pos++ = eap_type; /* Type */ - *pos = peap_version; /* Flags */ - return (u8 *) req; -} diff --git a/contrib/hostapd/eap_tls_common.h b/contrib/hostapd/eap_tls_common.h deleted file mode 100644 index 6c9d69603ed0..000000000000 --- a/contrib/hostapd/eap_tls_common.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * hostapd / EAP-TLS/PEAP/TTLS common functions - * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 { - struct tls_connection *conn; - - u8 *tls_out; - size_t tls_out_len; - size_t tls_out_pos; - size_t tls_out_limit; - u8 *tls_in; - size_t tls_in_len; - size_t tls_in_left; - size_t tls_in_total; - - int phase2; - - 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_PEAP_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_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data, - int verify_peer); -void eap_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data); -u8 * eap_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, - char *label, size_t len); -int eap_tls_data_reassemble(struct eap_sm *sm, struct eap_ssl_data *data, - u8 **in_data, size_t *in_len); -int eap_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data, - u8 *in_data, size_t in_len); -int eap_tls_buildReq_helper(struct eap_sm *sm, struct eap_ssl_data *data, - int eap_type, int peap_version, u8 id, - u8 **out_data, size_t *out_len); -u8 * eap_tls_build_ack(size_t *reqDataLen, u8 id, int eap_type, - int peap_version); - -#endif /* EAP_TLS_COMMON_H */ diff --git a/contrib/hostapd/eap_tlv.c b/contrib/hostapd/eap_tlv.c deleted file mode 100644 index b48e1861c57d..000000000000 --- a/contrib/hostapd/eap_tlv.c +++ /dev/null @@ -1,252 +0,0 @@ -/* - * hostapd / EAP-TLV (draft-josefsson-pppext-eap-tls-eap-07.txt) - * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "hostapd.h" -#include "common.h" -#include "eap_i.h" - - -/* EAP-TLV TLVs (draft-josefsson-ppext-eap-tls-eap-07.txt) */ -#define EAP_TLV_RESULT_TLV 3 /* Acknowledged Result */ -#define EAP_TLV_NAK_TLV 4 -#define EAP_TLV_CRYPTO_BINDING_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_RESULT_SUCCESS 1 -#define EAP_TLV_RESULT_FAILURE 2 - - -struct eap_tlv_data { - enum { CONTINUE, SUCCESS, FAILURE } state; -}; - - -static void * eap_tlv_init(struct eap_sm *sm) -{ - struct eap_tlv_data *data; - - data = wpa_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = CONTINUE; - - return data; -} - - -static void eap_tlv_reset(struct eap_sm *sm, void *priv) -{ - struct eap_tlv_data *data = priv; - free(data); -} - - -static u8 * eap_tlv_buildReq(struct eap_sm *sm, void *priv, int id, - size_t *reqDataLen) -{ - struct eap_hdr *req; - u8 *pos; - u16 status; - - if (sm->tlv_request == TLV_REQ_SUCCESS) { - status = EAP_TLV_RESULT_SUCCESS; - } else { - status = EAP_TLV_RESULT_FAILURE; - } - - *reqDataLen = sizeof(struct eap_hdr) + 1 + 6; - req = malloc(*reqDataLen); - if (req == NULL) - return NULL; - - req->code = EAP_CODE_REQUEST; - req->identifier = id; - req->length = host_to_be16(*reqDataLen); - pos = (u8 *) (req + 1); - *pos++ = EAP_TYPE_TLV; - *pos++ = 0x80; /* Mandatory */ - *pos++ = EAP_TLV_RESULT_TLV; - /* Length */ - *pos++ = 0; - *pos++ = 2; - /* Status */ - *pos++ = status >> 8; - *pos++ = status & 0xff; - - return (u8 *) req; -} - - -static Boolean eap_tlv_check(struct eap_sm *sm, void *priv, - u8 *respData, size_t respDataLen) -{ - struct eap_hdr *resp; - u8 *pos; - - resp = (struct eap_hdr *) respData; - pos = (u8 *) (resp + 1); - if (respDataLen < sizeof(*resp) + 1 || *pos != EAP_TYPE_TLV || - (ntohs(resp->length)) > respDataLen) { - wpa_printf(MSG_INFO, "EAP-TLV: Invalid frame"); - return TRUE; - } - - return FALSE; -} - - -static void eap_tlv_process(struct eap_sm *sm, void *priv, - u8 *respData, size_t respDataLen) -{ - struct eap_tlv_data *data = priv; - struct eap_hdr *resp; - u8 *pos; - size_t left; - u8 *result_tlv = NULL; - size_t result_tlv_len = 0; - int tlv_type, mandatory, tlv_len; - - resp = (struct eap_hdr *) respData; - pos = (u8 *) (resp + 1); - - /* Parse TLVs */ - left = be_to_host16(resp->length) - sizeof(struct eap_hdr) - 1; - pos = (u8 *) (resp + 1); - pos++; - wpa_hexdump(MSG_DEBUG, "EAP-TLV: 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-TLV: TLV underrun " - "(tlv_len=%d left=%lu)", tlv_len, - (unsigned long) left); - data->state = FAILURE; - return; - } - switch (tlv_type) { - case EAP_TLV_RESULT_TLV: - result_tlv = pos; - result_tlv_len = tlv_len; - break; - default: - wpa_printf(MSG_DEBUG, "EAP-TLV: Unsupported TLV Type " - "%d%s", tlv_type, - mandatory ? " (mandatory)" : ""); - if (mandatory) { - data->state = FAILURE; - return; - } - /* 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); - data->state = FAILURE; - return; - } - - /* Process supported TLVs */ - if (result_tlv) { - int status; - const char *requested; - - 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); - data->state = FAILURE; - return; - } - requested = sm->tlv_request == TLV_REQ_SUCCESS ? "Success" : - "Failure"; - status = ((int) result_tlv[0] << 8) | result_tlv[1]; - if (status == EAP_TLV_RESULT_SUCCESS) { - wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Success " - "- requested %s", requested); - if (sm->tlv_request == TLV_REQ_SUCCESS) - data->state = SUCCESS; - else - data->state = FAILURE; - - } else if (status == EAP_TLV_RESULT_FAILURE) { - wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Failure - " - "requested %s", requested); - if (sm->tlv_request == TLV_REQ_FAILURE) - data->state = SUCCESS; - else - data->state = FAILURE; - } else { - wpa_printf(MSG_INFO, "EAP-TLV: Unknown TLV Result " - "Status %d", status); - data->state = FAILURE; - } - } -} - - -static Boolean eap_tlv_isDone(struct eap_sm *sm, void *priv) -{ - struct eap_tlv_data *data = priv; - return data->state != CONTINUE; -} - - -static Boolean eap_tlv_isSuccess(struct eap_sm *sm, void *priv) -{ - struct eap_tlv_data *data = priv; - return data->state == SUCCESS; -} - - -int eap_server_tlv_register(void) -{ - struct eap_method *eap; - int ret; - - eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, - EAP_VENDOR_IETF, EAP_TYPE_TLV, "TLV"); - if (eap == NULL) - return -1; - - eap->init = eap_tlv_init; - eap->reset = eap_tlv_reset; - eap->buildReq = eap_tlv_buildReq; - eap->check = eap_tlv_check; - eap->process = eap_tlv_process; - eap->isDone = eap_tlv_isDone; - eap->isSuccess = eap_tlv_isSuccess; - - ret = eap_server_method_register(eap); - if (ret) - eap_server_method_free(eap); - return ret; -} diff --git a/contrib/hostapd/eap_ttls.c b/contrib/hostapd/eap_ttls.c deleted file mode 100644 index 1c0f17e764b7..000000000000 --- a/contrib/hostapd/eap_ttls.c +++ /dev/null @@ -1,1502 +0,0 @@ -/* - * hostapd / EAP-TTLS (draft-ietf-pppext-eap-ttls-05.txt) - * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "hostapd.h" -#include "common.h" -#include "eap_i.h" -#include "eap_tls_common.h" -#include "ms_funcs.h" -#include "md5.h" -#include "sha1.h" -#include "crypto.h" -#include "tls.h" -#include "eap_ttls.h" - - -/* Maximum supported PEAP version - * 0 = draft-ietf-pppext-eap-ttls-03.txt / draft-funk-eap-ttls-v0-00.txt - * 1 = draft-funk-eap-ttls-v1-00.txt - */ -#define EAP_TTLS_VERSION 0 /* TTLSv1 implementation is not yet complete */ - - -#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; -}; - - -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 int eap_ttls_avp_encapsulate(u8 **resp, size_t *resp_len, u32 avp_code, - int mandatory) -{ - u8 *avp, *pos; - - avp = malloc(sizeof(struct ttls_avp) + *resp_len + 4); - if (avp == NULL) { - free(*resp); - *resp_len = 0; - return -1; - } - - pos = eap_ttls_avp_hdr(avp, avp_code, 0, mandatory, *resp_len); - memcpy(pos, *resp, *resp_len); - pos += *resp_len; - AVP_PAD(avp, pos); - free(*resp); - *resp = avp; - *resp_len = pos - avp; - return 0; -} - - -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(u8 *buf, size_t len, struct eap_ttls_avp *parse) -{ - struct ttls_avp *avp; - u8 *pos; - int left; - - pos = buf; - left = len; - 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(* (u32 *) 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 = malloc(dlen); - if (parse->eap == NULL) { - wpa_printf(MSG_WARNING, "EAP-TTLS: " - "failed to allocate memory " - "for Phase 2 EAP data"); - goto fail; - } - memcpy(parse->eap, dpos, dlen); - parse->eap_len = dlen; - } else { - u8 *neweap = 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; - } - 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: - 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_tls_derive_key(sm, &data->ssl, "ttls challenge", - len); - } - - 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 = malloc(keys.client_random_len + keys.server_random_len); - challenge = malloc(len); - if (rnd == NULL || challenge == NULL) { - wpa_printf(MSG_INFO, "EAP-TTLS: No memory for implicit " - "challenge derivation"); - free(rnd); - free(challenge); - return NULL; - } - memcpy(rnd, keys.server_random, keys.server_random_len); - 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"); - free(rnd); - free(challenge); - return NULL; - } - - 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 = wpa_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_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_tls_ssl_deinit(sm, &data->ssl); - free(data); -} - - -static u8 * eap_ttls_build_start(struct eap_sm *sm, struct eap_ttls_data *data, - int id, size_t *reqDataLen) -{ - struct eap_hdr *req; - u8 *pos; - - *reqDataLen = sizeof(*req) + 2; - req = malloc(*reqDataLen); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-TTLS: Failed to allocate memory for" - " request"); - eap_ttls_state(data, FAILURE); - return NULL; - } - - req->code = EAP_CODE_REQUEST; - req->identifier = id; - req->length = htons(*reqDataLen); - pos = (u8 *) (req + 1); - *pos++ = EAP_TYPE_TTLS; - *pos = EAP_TLS_FLAGS_START | data->ttls_version; - - eap_ttls_state(data, PHASE1); - - return (u8 *) req; -} - - -static u8 * eap_ttls_build_req(struct eap_sm *sm, struct eap_ttls_data *data, - int id, size_t *reqDataLen) -{ - int res; - u8 *req; - - res = eap_tls_buildReq_helper(sm, &data->ssl, EAP_TYPE_TTLS, - data->ttls_version, id, &req, - reqDataLen); - - 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); - } - - if (res == 1) - return eap_tls_build_ack(reqDataLen, id, EAP_TYPE_TTLS, - data->ttls_version); - return req; -} - - -static u8 * eap_ttls_encrypt(struct eap_sm *sm, struct eap_ttls_data *data, - int id, u8 *plain, size_t plain_len, - size_t *out_len) -{ - int res; - u8 *pos; - struct eap_hdr *req; - - /* TODO: add support for fragmentation, if needed. This will need to - * add TLS Message Length field, if the frame is fragmented. */ - req = malloc(sizeof(struct eap_hdr) + 2 + data->ssl.tls_out_limit); - if (req == NULL) - return NULL; - - req->code = EAP_CODE_REQUEST; - req->identifier = id; - - pos = (u8 *) (req + 1); - *pos++ = EAP_TYPE_TTLS; - *pos++ = data->ttls_version; - - res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn, - plain, plain_len, - pos, data->ssl.tls_out_limit); - if (res < 0) { - wpa_printf(MSG_INFO, "EAP-TTLS: Failed to encrypt Phase 2 " - "data"); - free(req); - return NULL; - } - - *out_len = sizeof(struct eap_hdr) + 2 + res; - req->length = host_to_be16(*out_len); - return (u8 *) req; -} - - -static u8 * eap_ttls_build_phase2_eap_req(struct eap_sm *sm, - struct eap_ttls_data *data, - int id, size_t *reqDataLen) -{ - u8 *req, *encr_req; - size_t req_len; - - - req = data->phase2_method->buildReq(sm, data->phase2_priv, id, - &req_len); - if (req == NULL) - return NULL; - - wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS/EAP: Encapsulate Phase 2 data", - req, req_len); - - if (eap_ttls_avp_encapsulate(&req, &req_len, RADIUS_ATTR_EAP_MESSAGE, - 1) < 0) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Failed to encapsulate " - "packet"); - return NULL; - } - - wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS/EAP: Encrypt encapsulated Phase " - "2 data", req, req_len); - - encr_req = eap_ttls_encrypt(sm, data, id, req, req_len, reqDataLen); - free(req); - - return encr_req; -} - - -static u8 * eap_ttls_build_phase2_mschapv2(struct eap_sm *sm, - struct eap_ttls_data *data, - int id, size_t *reqDataLen) -{ - u8 *req, *encr_req, *pos, *end; - int ret; - size_t req_len; - - pos = req = 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 = 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); - memcpy(pos, "Failed", 6); - pos += 6; - AVP_PAD(req, pos); - } - - req_len = pos - req; - wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Encrypting Phase 2 " - "data", req, req_len); - - encr_req = eap_ttls_encrypt(sm, data, id, req, req_len, reqDataLen); - free(req); - - return encr_req; -} - - -static u8 * eap_ttls_build_phase_finished(struct eap_sm *sm, - struct eap_ttls_data *data, - int id, int final, - size_t *reqDataLen) -{ - int len; - struct eap_hdr *req; - u8 *pos; - const int max_len = 300; - - len = sizeof(struct eap_hdr) + 2 + max_len; - req = malloc(len); - if (req == NULL) - return NULL; - - req->code = EAP_CODE_REQUEST; - req->identifier = id; - - pos = (u8 *) (req + 1); - *pos++ = EAP_TYPE_TTLS; - *pos++ = data->ttls_version; - - len = tls_connection_ia_send_phase_finished(sm->ssl_ctx, - data->ssl.conn, - final, pos, max_len); - if (len < 0) { - free(req); - return NULL; - } - - *reqDataLen = sizeof(struct eap_hdr) + 2 + len; - req->length = host_to_be16(*reqDataLen); - - return (u8 *) req; -} - - -static u8 * eap_ttls_buildReq(struct eap_sm *sm, void *priv, int id, - size_t *reqDataLen) -{ - struct eap_ttls_data *data = priv; - - switch (data->state) { - case START: - return eap_ttls_build_start(sm, data, id, reqDataLen); - case PHASE1: - return eap_ttls_build_req(sm, data, id, reqDataLen); - case PHASE2_METHOD: - return eap_ttls_build_phase2_eap_req(sm, data, id, reqDataLen); - case PHASE2_MSCHAPV2_RESP: - return eap_ttls_build_phase2_mschapv2(sm, data, id, - reqDataLen); - case PHASE_FINISHED: - return eap_ttls_build_phase_finished(sm, data, id, 1, - reqDataLen); - default: - wpa_printf(MSG_DEBUG, "EAP-TTLS: %s - unexpected state %d", - __func__, data->state); - return NULL; - } -} - - -static Boolean eap_ttls_check(struct eap_sm *sm, void *priv, - u8 *respData, size_t respDataLen) -{ - struct eap_hdr *resp; - u8 *pos; - - resp = (struct eap_hdr *) respData; - pos = (u8 *) (resp + 1); - if (respDataLen < sizeof(*resp) + 2 || *pos != EAP_TYPE_TTLS || - (ntohs(resp->length)) > respDataLen) { - 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 = malloc(buf_len); - if (buf == NULL) - return -1; - WPA_PUT_BE16(buf, key_len); - 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); - 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) -{ - /* TODO: add support for verifying that the user entry accepts - * EAP-TTLS/PAP. */ - if (!sm->user || !sm->user->password || sm->user->password_hash) { - 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 || - 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[MD5_MAC_LEN]; - const u8 *addr[3]; - size_t len[3]; - - 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; - } - - /* TODO: add support for verifying that the user entry accepts - * EAP-TTLS/CHAP. */ - if (!sm->user || !sm->user->password || sm->user->password_hash) { - 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 (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"); - free(chal); - eap_ttls_state(data, FAILURE); - return; - } - free(chal); - - /* MD5(Ident + Password + Challenge) */ - addr[0] = password; - len[0] = 1; - addr[1] = sm->user->password; - len[1] = sm->user->password_len; - addr[2] = challenge; - len[2] = challenge_len; - md5_vector(3, addr, len, hash); - - if (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; - } - - /* TODO: add support for verifying that the user entry accepts - * EAP-TTLS/MSCHAP. */ - if (!sm->user || !sm->user->password) { - 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 (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"); - free(chal); - eap_ttls_state(data, FAILURE); - return; - } - 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 (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; - } - - /* TODO: add support for verifying that the user entry accepts - * EAP-TTLS/MSCHAPV2. */ - if (!sm->user || !sm->user->password) { - 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 (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"); - free(chal); - eap_ttls_state(data, FAILURE); - return; - } - 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 (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_sm_get_eap_methods(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 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; - const struct eap_method *m = data->phase2_method; - void *priv = data->phase2_priv; - - if (data->phase2_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); - eap_ttls_phase2_eap_init(sm, data, next_type); - } else { - eap_ttls_state(data, FAILURE); - } - return; - } - - if (m->check(sm, priv, in_data, in_len)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/EAP: Phase2 check() asked to " - "ignore the packet"); - return; - } - - m->process(sm, priv, in_data, in_len); - - 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); - 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; - } - - eap_ttls_phase2_eap_init(sm, data, next_type); -} - - -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 eap_hdr *resp, - u8 *in_data, size_t in_len) -{ - u8 *in_decrypted; - int len_decrypted, res; - struct eap_ttls_avp parse; - size_t buf_len; - - wpa_printf(MSG_DEBUG, "EAP-TTLS: received %lu bytes encrypted data for" - " Phase 2", (unsigned long) in_len); - - res = eap_tls_data_reassemble(sm, &data->ssl, &in_data, &in_len); - if (res < 0 || res == 1) - return; - - buf_len = in_len; - if (data->ssl.tls_in_total > buf_len) - buf_len = data->ssl.tls_in_total; - in_decrypted = malloc(buf_len); - if (in_decrypted == NULL) { - free(data->ssl.tls_in); - data->ssl.tls_in = NULL; - data->ssl.tls_in_len = 0; - wpa_printf(MSG_WARNING, "EAP-TTLS: failed to allocate memory " - "for decryption"); - return; - } - - len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn, - in_data, in_len, - in_decrypted, buf_len); - free(data->ssl.tls_in); - data->ssl.tls_in = NULL; - data->ssl.tls_in_len = 0; - if (len_decrypted < 0) { - wpa_printf(MSG_INFO, "EAP-TTLS: Failed to decrypt Phase 2 " - "data"); - free(in_decrypted); - eap_ttls_state(data, FAILURE); - return; - } - - if (data->state == PHASE_FINISHED) { - if (len_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); - } - - free(in_decrypted); - return; - } - - wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Decrypted Phase 2 EAP", - in_decrypted, len_decrypted); - - if (eap_ttls_avp_parse(in_decrypted, len_decrypted, &parse) < 0) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to parse AVPs"); - free(in_decrypted); - eap_ttls_state(data, FAILURE); - return; - } - - if (parse.user_name) { - free(sm->identity); - sm->identity = malloc(parse.user_name_len); - if (sm->identity) { - 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; - } - } - - 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: - free(in_decrypted); - free(parse.eap); - } - - -static void eap_ttls_process(struct eap_sm *sm, void *priv, - u8 *respData, size_t respDataLen) -{ - struct eap_ttls_data *data = priv; - struct eap_hdr *resp; - u8 *pos, flags; - int left; - unsigned int tls_msg_len; - int peer_version; - - resp = (struct eap_hdr *) respData; - pos = (u8 *) (resp + 1); - pos++; - flags = *pos++; - left = htons(resp->length) - sizeof(struct eap_hdr) - 2; - wpa_printf(MSG_DEBUG, "EAP-TTLS: Received packet(len=%lu) - " - "Flags 0x%02x", (unsigned long) respDataLen, flags); - peer_version = flags & EAP_PEAP_VERSION_MASK; - 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"); - eap_ttls_state(data, FAILURE); - return; - } - data->tls_ia_configured = 1; - } - - if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) { - if (left < 4) { - wpa_printf(MSG_INFO, "EAP-TTLS: Short frame with TLS " - "length"); - eap_ttls_state(data, FAILURE); - return; - } - tls_msg_len = (pos[0] << 24) | (pos[1] << 16) | (pos[2] << 8) | - pos[3]; - wpa_printf(MSG_DEBUG, "EAP-TTLS: TLS Message Length: %d", - tls_msg_len); - if (data->ssl.tls_in_left == 0) { - data->ssl.tls_in_total = tls_msg_len; - data->ssl.tls_in_left = tls_msg_len; - free(data->ssl.tls_in); - data->ssl.tls_in = NULL; - data->ssl.tls_in_len = 0; - } - pos += 4; - left -= 4; - } - - switch (data->state) { - case PHASE1: - if (eap_tls_process_helper(sm, &data->ssl, pos, left) < 0) { - wpa_printf(MSG_INFO, "EAP-TTLS: TLS processing " - "failed"); - eap_ttls_state(data, FAILURE); - } - break; - case PHASE2_START: - case PHASE2_METHOD: - case PHASE_FINISHED: - eap_ttls_process_phase2(sm, data, resp, pos, left); - break; - case PHASE2_MSCHAPV2_RESP: - if (data->mschapv2_resp_ok && left == 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 %d, expected " - "empty frame)", left); - eap_ttls_state(data, FAILURE); - } - break; - default: - wpa_printf(MSG_DEBUG, "EAP-TTLS: Unexpected state %d in %s", - data->state, __func__); - break; - } - - if (tls_connection_get_write_alerts(sm->ssl_ctx, data->ssl.conn) > 1) { - wpa_printf(MSG_INFO, "EAP-TTLS: Locally detected fatal error " - "in TLS processing"); - 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; - - 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 = malloc(keys.client_random_len + keys.server_random_len); - key = malloc(EAP_TLS_KEY_LEN); - if (rnd == NULL || key == NULL) { - wpa_printf(MSG_INFO, "EAP-TTLS: No memory for key derivation"); - free(rnd); - free(key); - return NULL; - } - memcpy(rnd, keys.client_random, keys.client_random_len); - 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"); - free(rnd); - 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); - - 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_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/contrib/hostapd/eap_ttls.h b/contrib/hostapd/eap_ttls.h deleted file mode 100644 index e0b2cbf45488..000000000000 --- a/contrib/hostapd/eap_ttls.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * EAP server/peer: EAP-TTLS (draft-ietf-pppext-eap-ttls-03.txt) - * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 { - u32 avp_code; - u32 avp_length; /* 8-bit flags, 24-bit length; - * length includes AVP header */ - /* optional 32-bit Vendor-ID */ - /* Data */ -}; - -struct ttls_avp_vendor { - u32 avp_code; - u32 avp_length; /* 8-bit flags, 24-bit length; - * length includes AVP header */ - u32 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/contrib/hostapd/eap_vendor_test.c b/contrib/hostapd/eap_vendor_test.c deleted file mode 100644 index 4f9c14b051e6..000000000000 --- a/contrib/hostapd/eap_vendor_test.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * hostapd / Test method for vendor specific (expanded) EAP type - * Copyright (c) 2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "hostapd.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 = wpa_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; - free(data); -} - - -static u8 * eap_vendor_test_buildReq(struct eap_sm *sm, void *priv, int id, - size_t *reqDataLen) -{ - struct eap_vendor_test_data *data = priv; - struct eap_hdr *req; - u8 *pos; - - *reqDataLen = sizeof(*req) + 8 + 1; - req = malloc(*reqDataLen); - if (req == NULL) { - wpa_printf(MSG_ERROR, "EAP-VENDOR-TEST: Failed to allocate " - "memory for request"); - return NULL; - } - - req->code = EAP_CODE_REQUEST; - req->identifier = id; - req->length = htons(*reqDataLen); - pos = (u8 *) (req + 1); - *pos++ = EAP_TYPE_EXPANDED; - WPA_PUT_BE24(pos, EAP_VENDOR_ID); - pos += 3; - WPA_PUT_BE32(pos, EAP_VENDOR_TYPE); - pos += 4; - *pos = data->state == INIT ? 1 : 3; - - return (u8 *) req; -} - - -static Boolean eap_vendor_test_check(struct eap_sm *sm, void *priv, - u8 *respData, size_t respDataLen) -{ - struct eap_hdr *resp; - u8 *pos; - size_t len; - int vendor; - u32 method; - - resp = (struct eap_hdr *) respData; - pos = (u8 *) (resp + 1); - if (respDataLen < sizeof(*resp)) - return TRUE; - len = ntohs(resp->length); - if (len > respDataLen) - return TRUE; - - if (len < sizeof(*resp) + 8 || *pos != EAP_TYPE_EXPANDED) { - wpa_printf(MSG_INFO, "EAP-VENDOR-TEST: Invalid frame"); - return TRUE; - } - pos++; - - vendor = WPA_GET_BE24(pos); - pos += 3; - method = WPA_GET_BE32(pos); - pos++; - - if (vendor != EAP_VENDOR_ID || method != EAP_VENDOR_TYPE) - return TRUE; - - return FALSE; -} - - -static void eap_vendor_test_process(struct eap_sm *sm, void *priv, - u8 *respData, size_t respDataLen) -{ - struct eap_vendor_test_data *data = priv; - struct eap_hdr *resp; - u8 *pos; - - resp = (struct eap_hdr *) respData; - pos = (u8 *) (resp + 1); - pos += 8; /* Skip expanded header */ - - 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 = malloc(key_len); - if (key == NULL) - return NULL; - - memset(key, 0x11, key_len / 2); - 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/contrib/hostapd/eapol_sm.c b/contrib/hostapd/eapol_sm.c deleted file mode 100644 index 18f25763cef8..000000000000 --- a/contrib/hostapd/eapol_sm.c +++ /dev/null @@ -1,1266 +0,0 @@ -/* - * hostapd / IEEE 802.1X Authenticator - EAPOL state machine - * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * $FreeBSD$ - */ - -#include "includes.h" - -#include "hostapd.h" -#include "ieee802_1x.h" -#include "eapol_sm.h" -#include "eloop.h" -#include "wpa.h" -#include "preauth.h" -#include "sta_info.h" -#include "eap.h" -#include "state_machine.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-REV-d11, Chap. 8.2 */ - -#define setPortAuthorized() \ -ieee802_1x_set_sta_authorized(sm->hapd, sm->sta, 1) -#define setPortUnauthorized() \ -ieee802_1x_set_sta_authorized(sm->hapd, sm->sta, 0) - -/* procedures */ -#define txCannedFail() ieee802_1x_tx_canned_eap(sm->hapd, sm->sta, 0) -#define txCannedSuccess() ieee802_1x_tx_canned_eap(sm->hapd, sm->sta, 1) -#define txReq() ieee802_1x_tx_req(sm->hapd, sm->sta) -#define sendRespToServer() ieee802_1x_send_resp_to_server(sm->hapd, sm->sta) -#define abortAuth() ieee802_1x_abort_auth(sm->hapd, sm->sta) -#define txKey() ieee802_1x_tx_key(sm->hapd, 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); - - -/* 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_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)); - } - } - - 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->currentId = 255; -} - - -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) { - if (sm->flags & EAPOL_SM_PREAUTH) - rsn_preauth_finished(sm->hapd, sm->sta, 0); - else - ieee802_1x_finished(sm->hapd, sm->sta, 0); - } -} - - -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->eapRestart = TRUE; - ieee802_1x_request_identity(sm->hapd, sm->sta); -} - - -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; - - hostapd_logger(sm->hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_WARNING, "authentication failed - " - "EAP type: %d (%s)", - sm->eap_type_authsrv, - eap_type_text(sm->eap_type_authsrv)); - if (sm->eap_type_authsrv != sm->eap_type_supp) { - hostapd_logger(sm->hapd, sm->addr, - HOSTAPD_MODULE_IEEE8021X, HOSTAPD_LEVEL_INFO, - "Supplicant used different EAP type: %d (%s)", - sm->eap_type_supp, - eap_type_text(sm->eap_type_supp)); - } - if (sm->flags & EAPOL_SM_PREAUTH) - rsn_preauth_finished(sm->hapd, sm->sta, 0); - else - ieee802_1x_finished(sm->hapd, sm->sta, 0); -} - - -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 (wpa_auth_sta_get_pmksa(sm->sta->wpa_sm)) - extra = " (PMKSA cache)"; - hostapd_logger(sm->hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_INFO, "authenticated - EAP type: %d (%s)" - "%s", sm->eap_type_authsrv, - eap_type_text(sm->eap_type_authsrv), extra); - if (sm->flags & EAPOL_SM_PREAUTH) - rsn_preauth_finished(sm->hapd, sm->sta, 1); - else - ieee802_1x_finished(sm->hapd, sm->sta, 1); -} - - -SM_STATE(AUTH_PAE, AUTHENTICATING) -{ - if (sm->auth_pae_state == AUTH_PAE_CONNECTING && sm->rx_identity) { - sm->authEntersAuthenticating++; - sm->rx_identity = FALSE; - } - - 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->portEnabled) - SM_ENTER(AUTH_PAE, INITIALIZE); - else if (sm->portControl == ForceAuthorized && - sm->portMode != sm->portControl && - !(sm->initialize || !sm->portEnabled)) - SM_ENTER(AUTH_PAE, FORCE_AUTH); - else if (sm->portControl == ForceUnauthorized && - sm->portMode != sm->portControl && - !(sm->initialize || !sm->portEnabled)) - SM_ENTER(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->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->eapReq && - sm->reAuthCount <= sm->reAuthMax) || - sm->eapSuccess || sm->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->eapNoReq = FALSE; - sm->authAbort = FALSE; -} - - -SM_STATE(BE_AUTH, REQUEST) -{ - SM_ENTRY_MA(BE_AUTH, REQUEST, be_auth); - - txReq(); - sm->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->eapNoReq = FALSE; - sm->aWhile = sm->serverTimeout; - sm->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); - - /* Note: IEEE 802.1X-REV-d11 has unconditional txReq() here. - * txCannelFail() is used as a workaround for the case where - * authentication server does not include EAP-Message with - * Access-Reject. */ - if (sm->last_eap_radius == NULL) - txCannedFail(); - else - 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->eapNoReq = FALSE; -} - - -SM_STEP(BE_AUTH) -{ - if (sm->portControl != Auto || sm->initialize || sm->authAbort) { - SM_ENTER(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->eapReq) - SM_ENTER(BE_AUTH, REQUEST); - else if (sm->eapTimeout) - SM_ENTER(BE_AUTH, TIMEOUT); - break; - case BE_AUTH_RESPONSE: - if (sm->eapNoReq) - SM_ENTER(BE_AUTH, IGNORE); - if (sm->eapReq) { - sm->backendAccessChallenges++; - SM_ENTER(BE_AUTH, REQUEST); - } else if (sm->aWhile == 0) - SM_ENTER(BE_AUTH, TIMEOUT); - else if (sm->eapFail) { - sm->backendAuthFails++; - SM_ENTER(BE_AUTH, FAIL); - } else if (sm->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->eapFail && sm->authStart) - SM_ENTER(BE_AUTH, FAIL); - else if (sm->eapReq && sm->authStart) - SM_ENTER(BE_AUTH, REQUEST); - else if (sm->eapSuccess && sm->authStart) - SM_ENTER(BE_AUTH, SUCCESS); - break; - case BE_AUTH_IGNORE: - if (sm->eapolEap) - SM_ENTER(BE_AUTH, RESPONSE); - else if (sm->eapReq) - SM_ENTER(BE_AUTH, REQUEST); - else if (sm->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; - wpa_auth_sm_event(sm->sta->wpa_sm, WPA_REAUTH_EAPOL); -} - - -SM_STEP(REAUTH_TIMER) -{ - if (sm->portControl != Auto || sm->initialize || - sm->authPortStatus == Unauthorized || !sm->reAuthEnabled) { - SM_ENTER(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->keyAvailable = FALSE; - sm->keyDone = TRUE; -} - - -SM_STEP(AUTH_KEY_TX) -{ - if (sm->initialize || sm->portControl != Auto) { - SM_ENTER(AUTH_KEY_TX, NO_KEY_TRANSMIT); - return; - } - - switch (sm->auth_key_tx_state) { - case AUTH_KEY_TX_NO_KEY_TRANSMIT: - if (sm->keyTxEnabled && sm->keyAvailable && sm->keyRun && - !wpa_auth_sta_wpa_version(sm->sta->wpa_sm)) - 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->keyAvailable) - 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->portEnabled) { - SM_ENTER(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(CTRL_DIR, IN_OR_BOTH); - return; - } - - switch (sm->ctrl_dir_state) { - case CTRL_DIR_FORCE_BOTH: - if (sm->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->portEnabled || !sm->operEdge) - SM_ENTER(CTRL_DIR, FORCE_BOTH); - break; - } -} - - - -struct eapol_state_machine * -eapol_sm_alloc(struct hostapd_data *hapd, struct sta_info *sta) -{ - struct eapol_state_machine *sm; - - sm = wpa_zalloc(sizeof(*sm)); - if (sm == NULL) { - printf("IEEE 802.1X port state allocation failed\n"); - return NULL; - } - sm->radius_identifier = -1; - memcpy(sm->addr, sta->addr, ETH_ALEN); - if (sta->flags & WLAN_STA_PREAUTH) - sm->flags |= EAPOL_SM_PREAUTH; - - sm->hapd = hapd; - sm->sta = sta; - - /* 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 = hapd->conf->eap_reauth_period; - sm->reAuthEnabled = hapd->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->portEnabled = FALSE; - sm->portControl = Auto; - - sm->keyAvailable = FALSE; - if (!hapd->conf->wpa && - (hapd->default_wep_key || hapd->conf->individual_wep_key_len > 0)) - sm->keyTxEnabled = TRUE; - else - sm->keyTxEnabled = FALSE; - if (hapd->conf->wpa) - sm->portValid = FALSE; - else - sm->portValid = TRUE; - - if (hapd->conf->eap_server) { - struct eap_config eap_conf; - memset(&eap_conf, 0, sizeof(eap_conf)); - eap_conf.ssl_ctx = hapd->ssl_ctx; - eap_conf.eap_sim_db_priv = hapd->eap_sim_db_priv; - sm->eap = eap_sm_init(sm, &eapol_cb, &eap_conf); - if (sm->eap == NULL) { - eapol_sm_free(sm); - return NULL; - } - } - - eapol_sm_initialize(sm); - - return sm; -} - - -void eapol_sm_free(struct eapol_state_machine *sm) -{ - if (sm == NULL) - return; - - eloop_cancel_timeout(eapol_port_timers_tick, sm->hapd, sm); - eloop_cancel_timeout(eapol_sm_step_cb, sm, NULL); - if (sm->eap) - eap_sm_deinit(sm->eap); - free(sm); -} - - -static int eapol_sm_sta_entry_alive(struct hostapd_data *hapd, u8 *addr) -{ - struct sta_info *sta; - sta = ap_get_sta(hapd, addr); - if (sta == NULL || sta->eapol_sm == NULL) - return 0; - return 1; -} - - -static void eapol_sm_step_run(struct eapol_state_machine *sm) -{ - struct hostapd_data *hapd = sm->hapd; - 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; - - memcpy(addr, sm->sta->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(hapd, addr)) - SM_STEP_RUN(BE_AUTH); - if (sm->initializing || eapol_sm_sta_entry_alive(hapd, addr)) - SM_STEP_RUN(REAUTH_TIMER); - if (sm->initializing || eapol_sm_sta_entry_alive(hapd, addr)) - SM_STEP_RUN(AUTH_KEY_TX); - if (sm->initializing || eapol_sm_sta_entry_alive(hapd, addr)) - SM_STEP_RUN(KEY_RX); - if (sm->initializing || eapol_sm_sta_entry_alive(hapd, 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_sm_step(sm); - return; - } - - if (eapol_sm_sta_entry_alive(hapd, addr) && sm->eap) { - if (eap_sm_step(sm->eap)) { - if (--max_steps > 0) - goto restart; - /* Re-run from eloop timeout */ - eapol_sm_step(sm); - return; - } - } - - if (eapol_sm_sta_entry_alive(hapd, addr)) - wpa_auth_sm_notify(sm->sta->wpa_sm); -} - - -static void eapol_sm_step_cb(void *eloop_ctx, void *timeout_ctx) -{ - struct eapol_state_machine *sm = eloop_ctx; - eapol_sm_step_run(sm); -} - - -void eapol_sm_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); -} - - -void eapol_sm_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, sm->hapd, sm); - eloop_register_timeout(1, 0, eapol_port_timers_tick, sm->hapd, sm); -} - - -#ifdef HOSTAPD_DUMP_STATE -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_sm_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->eapFail), _SB(sm->eapolEap), - prefix, _SB(sm->eapSuccess), _SB(sm->eapTimeout), - _SB(sm->initialize), _SB(sm->keyAvailable), - prefix, _SB(sm->keyDone), _SB(sm->keyRun), - _SB(sm->keyTxEnabled), port_type_txt(sm->portControl), - prefix, _SB(sm->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->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->eapNoReq), _SB(sm->eapReq), _SB(sm->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 -} -#endif /* HOSTAPD_DUMP_STATE */ - - -static Boolean eapol_sm_get_bool(void *ctx, enum eapol_bool_var variable) -{ - struct eapol_state_machine *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_eapReq: - return sm->eapReq; - case EAPOL_eapNoReq: - return sm->eapNoReq; - case EAPOL_portEnabled: - return sm->portEnabled; - case EAPOL_eapTimeout: - return sm->eapTimeout; - } - return FALSE; -} - - -static void eapol_sm_set_bool(void *ctx, enum eapol_bool_var variable, - Boolean value) -{ - struct eapol_state_machine *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_eapReq: - sm->eapReq = value; - break; - case EAPOL_eapNoReq: - sm->eapNoReq = value; - break; - case EAPOL_portEnabled: - sm->portEnabled = value; - break; - case EAPOL_eapTimeout: - sm->eapTimeout = value; - break; - } -} - - -static void eapol_sm_set_eapReqData(void *ctx, const u8 *eapReqData, - size_t eapReqDataLen) -{ - struct eapol_state_machine *sm = ctx; - if (sm == NULL) - return; - - free(sm->last_eap_radius); - sm->last_eap_radius = malloc(eapReqDataLen); - if (sm->last_eap_radius == NULL) - return; - memcpy(sm->last_eap_radius, eapReqData, eapReqDataLen); - sm->last_eap_radius_len = eapReqDataLen; -} - - -static void eapol_sm_set_eapKeyData(void *ctx, const u8 *eapKeyData, - size_t eapKeyDataLen) -{ - struct eapol_state_machine *sm = ctx; - struct hostapd_data *hapd; - - if (sm == NULL) - return; - - hapd = sm->hapd; - - if (eapKeyData && eapKeyDataLen >= 64) { - free(sm->eapol_key_sign); - free(sm->eapol_key_crypt); - sm->eapol_key_crypt = malloc(32); - if (sm->eapol_key_crypt) { - memcpy(sm->eapol_key_crypt, eapKeyData, 32); - sm->eapol_key_crypt_len = 32; - } - sm->eapol_key_sign = malloc(32); - if (sm->eapol_key_sign) { - memcpy(sm->eapol_key_sign, eapKeyData + 32, 32); - sm->eapol_key_sign_len = 32; - } - if (hapd->default_wep_key || - hapd->conf->individual_wep_key_len > 0 || - hapd->conf->wpa) - sm->keyAvailable = TRUE; - } else { - free(sm->eapol_key_sign); - free(sm->eapol_key_crypt); - sm->eapol_key_sign = NULL; - sm->eapol_key_crypt = NULL; - sm->eapol_key_sign_len = 0; - sm->eapol_key_crypt_len = 0; - sm->keyAvailable = FALSE; - } -} - - -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; - const struct hostapd_eap_user *eap_user; - int i, count; - - eap_user = hostapd_get_eap_user(sm->hapd->conf, identity, - identity_len, phase2); - if (eap_user == NULL) - return -1; - - 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 = malloc(eap_user->password_len); - if (user->password == NULL) - return -1; - memcpy(user->password, eap_user->password, - eap_user->password_len); - user->password_len = eap_user->password_len; - } - user->force_version = eap_user->force_version; - - return 0; -} - - -static const char * eapol_sm_get_eap_req_id_text(void *ctx, size_t *len) -{ - struct eapol_state_machine *sm = ctx; - *len = sm->hapd->conf->eap_req_id_text_len; - return sm->hapd->conf->eap_req_id_text; -} - - -static struct eapol_callbacks eapol_cb = -{ - .get_bool = eapol_sm_get_bool, - .set_bool = eapol_sm_set_bool, - .set_eapReqData = eapol_sm_set_eapReqData, - .set_eapKeyData = eapol_sm_set_eapKeyData, - .get_eap_user = eapol_sm_get_eap_user, - .get_eap_req_id_text = eapol_sm_get_eap_req_id_text, -}; - - -int eapol_sm_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_sm_step(sm); - - return 0; -} diff --git a/contrib/hostapd/eapol_sm.h b/contrib/hostapd/eapol_sm.h deleted file mode 100644 index dcb5ee9b3196..000000000000 --- a/contrib/hostapd/eapol_sm.h +++ /dev/null @@ -1,210 +0,0 @@ -/* - * hostapd / IEEE 802.1X Authenticator - EAPOL state machine - * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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_SM_H -#define EAPOL_SM_H - -#include "defs.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 eap_sm; - -struct radius_attr_data { - u8 *data; - size_t len; -}; - -struct radius_class_data { - struct radius_attr_data *attr; - size_t count; -}; - -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 eapFail; - Boolean eapolEap; - Boolean eapSuccess; - Boolean eapTimeout; - Boolean initialize; - Boolean keyAvailable; - Boolean keyDone; - Boolean keyRun; - Boolean keyTxEnabled; - PortTypes portControl; - Boolean portEnabled; - 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; - Boolean eapRestart; - 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; - /* variables */ - Boolean eapNoReq; - Boolean eapReq; - Boolean eapResp; - /* 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 */ -#define EAPOL_SM_PREAUTH BIT(0) - int flags; /* EAPOL_SM_* */ - - int radius_identifier; - /* TODO: check when the last messages can be released */ - struct radius_msg *last_recv_radius; - u8 *last_eap_supp; /* last received EAP Response from Supplicant */ - size_t last_eap_supp_len; - u8 *last_eap_radius; /* last received EAP Response from Authentication - * Server */ - size_t last_eap_radius_len; - 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; - - Boolean rx_identity; /* set to TRUE on reception of - * EAP-Response/Identity */ - - struct eap_sm *eap; - - /* currentId was removed in IEEE 802.1X-REV, but it is needed to filter - * out EAP-Responses to old packets (e.g., to two EAP-Request/Identity - * packets that are often sent in the beginning of the authentication). - */ - u8 currentId; - - Boolean initializing; /* in process of initializing state machines */ - Boolean changed; - - /* Somewhat nasty pointers to global hostapd and STA data to avoid - * passing these to every function */ - struct hostapd_data *hapd; - struct sta_info *sta; -}; - - -struct eapol_state_machine *eapol_sm_alloc(struct hostapd_data *hapd, - struct sta_info *sta); -void eapol_sm_free(struct eapol_state_machine *sm); -void eapol_sm_step(struct eapol_state_machine *sm); -void eapol_sm_initialize(struct eapol_state_machine *sm); -void eapol_sm_dump_state(FILE *f, const char *prefix, - struct eapol_state_machine *sm); -int eapol_sm_eap_pending_cb(struct eapol_state_machine *sm, void *ctx); - -#endif /* EAPOL_SM_H */ diff --git a/contrib/hostapd/eloop.c b/contrib/hostapd/eloop.c deleted file mode 100644 index 232e7533cab2..000000000000 --- a/contrib/hostapd/eloop.c +++ /dev/null @@ -1,531 +0,0 @@ -/* - * Event loop based on select() loop - * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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; - eloop_sock_handler handler; -}; - -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_sock_table { - int count; - struct eloop_sock *table; - int changed; -}; - -struct eloop_data { - void *user_data; - - int max_sock; - - struct eloop_sock_table readers; - struct eloop_sock_table writers; - struct eloop_sock_table exceptions; - - 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 *user_data) -{ - os_memset(&eloop, 0, sizeof(eloop)); - eloop.user_data = user_data; - 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; - - 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; - table->count++; - table->table = tmp; - if (sock > eloop.max_sock) - eloop.max_sock = sock; - table->changed = 1; - - 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; - 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; -} - - -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) - 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, *prev; - - timeout = os_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(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; -} - - -#ifndef CONFIG_NATIVE_WINDOWS -static void eloop_handle_alarm(int sig) -{ - fprintf(stderr, "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.user_data, - 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) { - printf("eloop_run - malloc failed\n"); - goto out; - } - - while (!eloop.terminate && - (eloop.timeout || eloop.readers.count > 0 || - eloop.writers.count > 0 || eloop.exceptions.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; -#if 0 - printf("next timeout in %lu.%06lu sec\n", - tv.sec, tv.usec); -#endif - _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, - eloop.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 */ - 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 (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; - - timeout = eloop.timeout; - while (timeout != NULL) { - prev = timeout; - timeout = timeout->next; - os_free(prev); - } - 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); -} - - -void * eloop_get_user_data(void) -{ - return eloop.user_data; -} diff --git a/contrib/hostapd/eloop.h b/contrib/hostapd/eloop.h deleted file mode 100644 index 4dd2871760df..000000000000 --- a/contrib/hostapd/eloop.h +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Event loop - * Copyright (c) 2002-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 - * @eloop_ctx: Registered callback context data (global user_data from - * eloop_init() call) - * @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 *eloop_ctx, - void *signal_ctx); - -/** - * eloop_init() - Initialize global event loop data - * @user_data: Pointer to global data passed as eloop_ctx to signal handlers - * Returns: 0 on success, -1 on failure - * - * This function must be called before any other eloop_* function. user_data - * can be used to configure a global (to the process) pointer that will be - * passed as eloop_ctx parameter to signal handlers. - */ -int eloop_init(void *user_data); - -/** - * 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 <handler,eloop_data,user_data> 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_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. - * - * Signals are 'global' events and there is no local eloop_data pointer like - * with other handlers. The global user_data pointer registered with - * eloop_init() will be used as eloop_ctx for signal handlers. - */ -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. - * - * Signals are 'global' events and there is no local eloop_data pointer like - * with other handlers. The global user_data pointer registered with - * eloop_init() will be used as eloop_ctx for signal handlers. - * - * 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. - * - * Signals are 'global' events and there is no local eloop_data pointer like - * with other handlers. The global user_data pointer registered with - * eloop_init() will be used as eloop_ctx for signal handlers. - * - * 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); - -/** - * eloop_get_user_data - Get global user data - * Returns: user_data pointer that was registered with eloop_init() - */ -void * eloop_get_user_data(void); - -#endif /* ELOOP_H */ diff --git a/contrib/hostapd/eloop_none.c b/contrib/hostapd/eloop_none.c deleted file mode 100644 index 6943109d955f..000000000000 --- a/contrib/hostapd/eloop_none.c +++ /dev/null @@ -1,390 +0,0 @@ -/* - * Event loop - empty template (basic structure, but no OS specific operations) - * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 { - void *user_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 *user_data) -{ - memset(&eloop, 0, sizeof(eloop)); - eloop.user_data = user_data; - 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; -} - - -/* 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 - */ -} - - -void * eloop_get_user_data(void) -{ - return eloop.user_data; -} diff --git a/contrib/hostapd/eloop_win.c b/contrib/hostapd/eloop_win.c deleted file mode 100644 index 73f0eafeeb8b..000000000000 --- a/contrib/hostapd/eloop_win.c +++ /dev/null @@ -1,604 +0,0 @@ -/* - * Event loop based on Windows events and WaitForMultipleObjects - * Copyright (c) 2002-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 <winsock2.h> - -#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 { - void *user_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 *user_data) -{ - os_memset(&eloop, 0, sizeof(eloop)); - eloop.user_data = user_data; - 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; - - timeout = os_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(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; -} - - -/* 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); - } - } - - if (eloop.term_signal.signaled) { - eloop.term_signal.signaled = 0; - eloop.term_signal.handler(eloop.term_signal.sig, - eloop.user_data, - 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)) { - 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; - } - - 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); -} - - -void * eloop_get_user_data(void) -{ - return eloop.user_data; -} diff --git a/contrib/hostapd/hlr_auc_gw.c b/contrib/hostapd/hlr_auc_gw.c deleted file mode 100644 index a587702c5029..000000000000 --- a/contrib/hostapd/hlr_auc_gw.c +++ /dev/null @@ -1,588 +0,0 @@ -/* - * HLR/AuC testing gateway for hostapd EAP-SIM/AKA database/authenticator - * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 <IMSI> <max_chal> - * SIM-RESP-AUTH <IMSI> Kc1:SRES1:RAND1 Kc2:SRES2:RAND2 [Kc3:SRES3:RAND3] - * SIM-RESP-AUTH <IMSI> FAILURE - * - * EAP-AKA / UMTS query/response: - * AKA-REQ-AUTH <IMSI> - * AKA-RESP-AUTH <IMSI> <RAND> <AUTN> <IK> <CK> <RES> - * AKA-RESP-AUTH <IMSI> FAILURE - * - * EAP-AKA / UMTS AUTS (re-synchronization): - * AKA-AUTS <IMSI> <AUTS> <RAND> - * - * 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 <stdlib.h> -#include <stdio.h> -#include <unistd.h> -#include <signal.h> -#include <string.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/un.h> - -#include "common.h" -#include "milenage.h" - -static const char *default_socket_path = "/tmp/hlr_auc_gw.sock"; -static const char *socket_path; -static const char *default_gsm_triplet_file = "hostapd.sim_db"; -static const char *gsm_triplet_file; -static int serv_sock = -1; - -/* 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; - strncpy(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_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; - } - strncpy(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) -{ - FILE *f; - int count, max_chal, ret; - char buf[80], *pos; - char reply[1000], *rpos, *rend; - struct milenage_parameters *m; - - 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++) { - os_get_random(_rand, 16); - 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; - } - - /* TODO: could read triplet file into memory during startup and then - * have pointer for IMSI to allow more than three first entries to be - * used. */ - f = fopen(gsm_triplet_file, "r"); - if (f == NULL) { - printf("Could not open GSM triplet file '%s'\n", - gsm_triplet_file); - ret = snprintf(rpos, rend - rpos, " FAILURE"); - if (ret < 0 || ret >= rend - rpos) - return; - rpos += ret; - goto send; - } - - count = 0; - while (count < max_chal && fgets(buf, sizeof(buf), f)) { - /* Parse IMSI:Kc:SRES:RAND and match IMSI with identity. */ - buf[sizeof(buf) - 1] = '\0'; - pos = buf; - while (*pos != '\0' && *pos != '\n') - pos++; - if (*pos == '\n') - *pos = '\0'; - if (pos - buf < 60 || pos[0] == '#') - continue; - - pos = strchr(buf, ':'); - if (pos == NULL) - continue; - *pos++ = '\0'; - if (strcmp(buf, imsi) != 0) - continue; - - ret = snprintf(rpos, rend - rpos, " %s", pos); - if (ret < 0 || ret >= rend - rpos) { - fclose(f); - return; - } - rpos += ret; - count++; - } - - fclose(f); - - 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 <IMSI> <RAND> <AUTN> <IK> <CK> <RES> */ - 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) { - os_get_random(_rand, EAP_AKA_RAND_LEN); - 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 <IMSI> <AUTS> <RAND> */ - - 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 milenage_parameters *m, *prev; - - 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-2006, Jouni Malinen <j@w1.fi>\n" - "\n" - "usage:\n" - "hlr_auc_gw [-h] [-s<socket path>] [-g<triplet file>] " - "[-m<milenage file>]\n" - "\n" - "options:\n" - " -h = show this usage help\n" - " -s<socket path> = path for UNIX domain socket\n" - " (default: %s)\n" - " -g<triplet file> = path for GSM authentication triplets\n" - " (default: %s)\n" - " -m<milenage file> = path for Milenage keys\n", - default_socket_path, default_gsm_triplet_file); -} - - -int main(int argc, char *argv[]) -{ - int c; - char *milenage_file = NULL; - - socket_path = default_socket_path; - gsm_triplet_file = default_gsm_triplet_file; - - 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 (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/contrib/hostapd/hlr_auc_gw.milenage_db b/contrib/hostapd/hlr_auc_gw.milenage_db deleted file mode 100644 index fa15d53853b6..000000000000 --- a/contrib/hostapd/hlr_auc_gw.milenage_db +++ /dev/null @@ -1,9 +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 diff --git a/contrib/hostapd/hostap_common.h b/contrib/hostapd/hostap_common.h deleted file mode 100644 index 1e38df38fafb..000000000000 --- a/contrib/hostapd/hostap_common.h +++ /dev/null @@ -1,216 +0,0 @@ -/* - * hostapd / Kernel driver communication with Linux Host AP driver - * Copyright (c) 2002-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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_COMMON_H -#define HOSTAP_COMMON_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 \ -((int) (&((struct prism2_hostapd_param *) 0)->u.rid.data)) -#define PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN \ -((int) (&((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_COMMON_H */ diff --git a/contrib/hostapd/hostapd.8 b/contrib/hostapd/hostapd.8 deleted file mode 100644 index 9258512fd55e..000000000000 --- a/contrib/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 <PID file>] <configuration file(s)> -.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, Prism54 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 <PID file> -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 <j@w1.fi>. -.PP -This manual page was written by Faidon Liambotis <faidon@cube.gr>, -for the Debian project (but may be used by others). diff --git a/contrib/hostapd/hostapd.accept b/contrib/hostapd/hostapd.accept deleted file mode 100644 index 57122b663449..000000000000 --- a/contrib/hostapd/hostapd.accept +++ /dev/null @@ -1,5 +0,0 @@ -# List of MAC addresses that are allowed to authenticate (IEEE 802.11) -# with the AP. -00:11:22:33:44:55 -00:66:77:88:99:aa -00:00:22:33:44:55 diff --git a/contrib/hostapd/hostapd.c b/contrib/hostapd/hostapd.c deleted file mode 100644 index 87a552379646..000000000000 --- a/contrib/hostapd/hostapd.c +++ /dev/null @@ -1,1936 +0,0 @@ -/* - * hostapd / Initialization and configuration - * Copyright (c) 2002-2008, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 <syslog.h> -#endif /* CONFIG_NATIVE_WINDOWS */ - -#include "eloop.h" -#include "hostapd.h" -#include "ieee802_1x.h" -#include "ieee802_11.h" -#include "beacon.h" -#include "hw_features.h" -#include "accounting.h" -#include "eapol_sm.h" -#include "iapp.h" -#include "ap.h" -#include "ieee802_11_auth.h" -#include "ap_list.h" -#include "sta_info.h" -#include "driver.h" -#include "radius_client.h" -#include "radius_server.h" -#include "wpa.h" -#include "preauth.h" -#include "wme.h" -#include "vlan_init.h" -#include "ctrl_iface.h" -#include "tls.h" -#include "eap_sim_db.h" -#include "eap.h" -#include "version.h" - - -struct hapd_interfaces { - size_t count; - struct hostapd_iface **iface; -}; - -unsigned char rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; - - -extern int wpa_debug_level; -extern int wpa_debug_show_keys; -extern int wpa_debug_timestamp; - - -void hostapd_logger(struct hostapd_data *hapd, const u8 *addr, - unsigned int module, int level, const char *fmt, ...) -{ - char *format, *module_str; - int maxlen; - va_list ap; - int conf_syslog_level, conf_stdout_level; - unsigned int conf_syslog, conf_stdout; - - maxlen = strlen(fmt) + 100; - format = 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) - snprintf(format, maxlen, "%s: STA " MACSTR "%s%s: %s", - hapd->conf->iface, MAC2STR(addr), - module_str ? " " : "", module_str, fmt); - else if (hapd && hapd->conf) - snprintf(format, maxlen, "%s:%s%s %s", - hapd->conf->iface, module_str ? " " : "", - module_str, fmt); - else if (addr) - snprintf(format, maxlen, "STA " MACSTR "%s%s: %s", - MAC2STR(addr), module_str ? " " : "", - module_str, fmt); - else - snprintf(format, maxlen, "%s%s%s", - module_str, module_str ? ": " : "", fmt); - - if ((conf_stdout & module) && level >= conf_stdout_level) { - wpa_debug_print_timestamp(); - va_start(ap, fmt); - vprintf(format, ap); - va_end(ap); - printf("\n"); - } - -#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; - } - va_start(ap, fmt); - vsyslog(priority, format, ap); - va_end(ap); - } -#endif /* CONFIG_NATIVE_WINDOWS */ - - free(format); -} - - -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) { - snprintf(buf, buflen, "%s", inet_ntoa(addr->u.v4)); - } 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 (memcpy(&a->u.v6, &b->u.v6, sizeof(a->u.v6)) - != 0) - return 1; - break; -#endif /* CONFIG_IPV6 */ - } - - return 0; -} - - -static void hostapd_deauth_all_stas(struct hostapd_data *hapd) -{ -#if 0 - u8 addr[ETH_ALEN]; - - memset(addr, 0xff, ETH_ALEN); - hostapd_sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID); -#else - /* 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 a while - * until the issue has been resolved. */ -#endif -} - - -/** - * hostapd_prune_associations - Remove extraneous associations - * @hapd: Pointer to BSS data for the most recent association - * @sta: Pointer to the associated STA data - * - * This function looks through all radios and BSS's for previous - * (stale) associations of STA. If any are found they are removed. - */ -static void hostapd_prune_associations(struct hostapd_data *hapd, - struct sta_info *sta) -{ - struct sta_info *osta; - struct hostapd_data *ohapd; - size_t i, j; - struct hapd_interfaces *interfaces = eloop_get_user_data(); - - for (i = 0; i < interfaces->count; i++) { - for (j = 0; j < interfaces->iface[i]->num_bss; j++) { - ohapd = interfaces->iface[i]->bss[j]; - if (ohapd == hapd) - continue; - osta = ap_get_sta(ohapd, sta->addr); - if (!osta) - continue; - - ap_sta_disassociate(ohapd, osta, - WLAN_REASON_UNSPECIFIED); - } - } -} - - -/** - * 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 for ieee802_11.c for drivers that export MLME to hostapd and - * from driver_*.c 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_sta_deauth(hapd, sta->addr, - WLAN_REASON_MICHAEL_MIC_FAILURE); - return; - } - - hostapd_prune_associations(hapd, sta); - - /* IEEE 802.11F (IAPP) */ - if (hapd->conf->ieee802_11f) - iapp_new_station(hapd->iapp, sta); - - /* 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); - - hostapd_wme_sta_config(hapd, sta); - - /* Start IEEE 802.1X authentication process for new stations */ - ieee802_1x_new_station(hapd, sta); - if (reassoc) - wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH); - else - wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm); -} - - -#ifdef EAP_SERVER -static int hostapd_sim_db_cb_sta(struct hostapd_data *hapd, - struct sta_info *sta, void *ctx) -{ - if (eapol_sm_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) - radius_server_eap_pending_cb(hapd->radius_srv, session_ctx); -} -#endif /* EAP_SERVER */ - - -static void handle_term(int sig, void *eloop_ctx, void *signal_ctx) -{ - printf("Signal %d received - terminating\n", sig); - eloop_terminate(); -} - - -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->rsn_preauth = conf->rsn_preauth; - wconf->eapol_version = conf->eapol_version; - wconf->peerkey = conf->peerkey; - wconf->wme_enabled = conf->wme_enabled; -#ifdef CONFIG_IEEE80211W - wconf->ieee80211w = conf->ieee80211w; -#endif /* CONFIG_IEEE80211W */ -} - - -#ifndef CONFIG_NATIVE_WINDOWS -static void handle_reload(int sig, void *eloop_ctx, void *signal_ctx) -{ - struct hapd_interfaces *hapds = (struct hapd_interfaces *) eloop_ctx; - struct hostapd_config *newconf; - size_t i; - struct wpa_auth_config wpa_auth_conf; - - printf("Signal %d received - reloading configuration\n", sig); - - for (i = 0; i < hapds->count; i++) { - struct hostapd_data *hapd = hapds->iface[i]->bss[0]; - newconf = hostapd_config_read(hapds->iface[i]->config_fname); - if (newconf == NULL) { - printf("Failed to read new configuration file - " - "continuing with old.\n"); - continue; - } - /* TODO: update dynamic data based on changed configuration - * items (e.g., open/close sockets, remove stations added to - * deny list, etc.) */ - radius_client_flush(hapd->radius, 0); - hostapd_config_free(hapd->iconf); - - hostapd_wpa_auth_conf(&newconf->bss[0], &wpa_auth_conf); - wpa_reconfig(hapd->wpa_auth, &wpa_auth_conf); - - hapd->iconf = newconf; - hapd->conf = &newconf->bss[0]; - hapds->iface[i]->conf = newconf; - - if (hostapd_setup_wpa_psk(hapd->conf)) { - wpa_printf(MSG_ERROR, "Failed to re-configure WPA PSK " - "after reloading configuration"); - } - } -} - - -#ifdef HOSTAPD_DUMP_STATE -static void hostapd_dump_state(struct hostapd_data *hapd) -{ - FILE *f; - time_t now; - struct sta_info *sta; - int i; - char *buf; - - if (!hapd->conf->dump_log_name) { - printf("Dump file not defined - ignoring dump request\n"); - return; - } - - printf("Dumping hostapd state to '%s'\n", hapd->conf->dump_log_name); - f = fopen(hapd->conf->dump_log_name, "w"); - if (f == NULL) { - printf("Could not open dump file '%s' for writing.\n", - 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\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]" : ""), - (sta->flags & WLAN_STA_AUTHORIZED ? "[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_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); - } - - buf = 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); - - 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); - free(buf); - } - fclose(f); -} -#endif /* HOSTAPD_DUMP_STATE */ - - -static void handle_dump_state(int sig, void *eloop_ctx, void *signal_ctx) -{ -#ifdef HOSTAPD_DUMP_STATE - struct hapd_interfaces *hapds = (struct hapd_interfaces *) eloop_ctx; - size_t i, j; - - for (i = 0; i < hapds->count; i++) { - struct hostapd_iface *hapd_iface = hapds->iface[i]; - for (j = 0; j < hapd_iface->num_bss; j++) - hostapd_dump_state(hapd_iface->bss[j]); - } -#endif /* HOSTAPD_DUMP_STATE */ -} -#endif /* CONFIG_NATIVE_WINDOWS */ - -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_set_encryption(ifname, hapd, "none", NULL, i, NULL, - 0, i == 0 ? 1 : 0)) { - printf("Failed to clear default encryption keys " - "(ifname=%s keyidx=%d)\n", ifname, i); - } - } -} - - -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_set_encryption(hapd->conf->iface, - hapd, "WEP", NULL, idx, - ssid->wep.key[idx], - ssid->wep.len[idx], - idx == ssid->wep.idx)) { - printf("Could not set WEP encryption.\n"); - 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_set_encryption(ifname, hapd, "WEP", NULL, - idx, key->key[idx], - key->len[idx], - idx == key->idx)) { - printf("Could not set dynamic VLAN WEP " - "encryption.\n"); - 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) -{ - hostapd_ctrl_iface_deinit(hapd); - - free(hapd->default_wep_key); - hapd->default_wep_key = NULL; - iapp_deinit(hapd->iapp); - hapd->iapp = NULL; - accounting_deinit(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); - vlan_deinit(hapd); - hostapd_acl_deinit(hapd); - radius_client_deinit(hapd->radius); - hapd->radius = NULL; - radius_server_deinit(hapd->radius_srv); - hapd->radius_srv = NULL; - - hostapd_wireless_event_deinit(hapd); - -#ifdef EAP_TLS_FUNCS - if (hapd->ssl_ctx) { - tls_deinit(hapd->ssl_ctx); - hapd->ssl_ctx = NULL; - } -#endif /* EAP_TLS_FUNCS */ - -#ifdef EAP_SERVER - if (hapd->eap_sim_db_priv) { - eap_sim_db_deinit(hapd->eap_sim_db_priv); - hapd->eap_sim_db_priv = NULL; - } -#endif /* EAP_SERVER */ - - if (hapd->interface_added && - hostapd_bss_remove(hapd, hapd->conf->iface)) { - printf("Failed to remove BSS interface %s\n", - hapd->conf->iface); - } -} - - -/** - * 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; - free(iface->current_rates); - iface->current_rates = NULL; - ap_list_deinit(iface); - hostapd_config_free(iface->conf); - iface->conf = NULL; - - free(iface->config_fname); - free(iface->bss); - 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) - return 0; - - for (i = 0; i < 4; i++) { - if (hapd->conf->ssid.wep.key[i] && - hostapd_set_encryption(iface, hapd, "WEP", NULL, - i, hapd->conf->ssid.wep.key[i], - hapd->conf->ssid.wep.len[i], - i == hapd->conf->ssid.wep.idx)) { - printf("Could not set WEP encryption.\n"); - 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; - - wpa_printf(MSG_DEBUG, "Flushing old station entries"); - if (hostapd_flush(hapd)) { - printf("Could not connect to kernel driver.\n"); - ret = -1; - } - wpa_printf(MSG_DEBUG, "Deauthenticate all stations"); - hostapd_deauth_all_stas(hapd); - - return ret; -} - - -static void hostapd_wpa_auth_logger(void *ctx, const u8 *addr, - logger_level level, const char *txt) -{ - 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); -} - - -static void hostapd_wpa_auth_disconnect(void *ctx, const u8 *addr, - u16 reason) -{ - struct hostapd_data *hapd = ctx; - struct sta_info *sta; - - wpa_printf(MSG_DEBUG, "%s: WPA authenticator requests disconnect: " - "STA " MACSTR " reason %d", - __func__, MAC2STR(addr), reason); - - sta = ap_get_sta(hapd, addr); - hostapd_sta_deauth(hapd, addr, reason); - if (sta == NULL) - return; - sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_AUTHORIZED); - eloop_cancel_timeout(ap_handle_timer, hapd, sta); - eloop_register_timeout(0, 0, ap_handle_timer, hapd, sta); - sta->timeout_next = STA_REMOVE; -} - - -static void hostapd_wpa_auth_mic_failure_report(void *ctx, const u8 *addr) -{ - struct hostapd_data *hapd = ctx; - ieee80211_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->keyAvailable = 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->keyAvailable; - 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_pmk(void *ctx, const u8 *addr, u8 *pmk, - size_t *len) -{ - struct hostapd_data *hapd = ctx; - 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_crypt(sta->eapol_sm, &keylen); - if (key == NULL) - return -1; - - if (keylen > *len) - keylen = WPA_PMK_LEN; - memcpy(pmk, key, keylen); - *len = keylen; - return 0; -} - - -static int hostapd_wpa_auth_set_key(void *ctx, int vlan_id, const char *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_set_encryption(ifname, hapd, alg, addr, idx, - key, key_len, 1); -} - - -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_get_seqnum_igtk(void *ctx, const u8 *addr, int idx, - u8 *seq) -{ - struct hostapd_data *hapd = ctx; - return hostapd_get_seqnum_igtk(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; - return hostapd_send_eapol(hapd, addr, data, data_len, encrypt); -} - - -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; -} - - -/** - * 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; - - /* 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) - continue; - - for (i = 0; i < ETH_ALEN; i++) { - mask[i] |= - iface->conf->bss[j].bssid[i] ^ - hapd->own_addr[i]; - } - } - - 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) - return -1; - - 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; - - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "BSS count %lu, BSSID mask " - MACSTR " (%d bits)\n", - (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) { - printf("Driver did not accept BSSID mask " MACSTR " for start " - "address " MACSTR ".\n", - MAC2STR(mask), MAC2STR(hapd->own_addr)); - return -1; - } - - for (i = 0; i < ETH_ALEN; i++) { - if ((hapd->own_addr[i] & mask[i]) != hapd->own_addr[i]) { - printf("Invalid BSSID mask " MACSTR " for start " - "address " MACSTR ".\n" - "Start address must be the first address in the" - " block (i.e., addr AND mask == addr).\n", - MAC2STR(mask), MAC2STR(hapd->own_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; - - 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. */ - memcpy(hapd->own_addr, hapd->conf->bssid, ETH_ALEN); - - if (hostapd_mac_comp(hapd->own_addr, - hapd->iface->bss[0]->own_addr) == - 0) { - printf("BSS '%s' may not have BSSID " - "set to the MAC address of the radio\n", - hapd->conf->iface); - return -1; - } - } - - hapd->interface_added = 1; - if (hostapd_bss_add(hapd->iface->bss[0], hapd->conf->iface, - hapd->own_addr)) { - printf("Failed to add BSS (BSSID=" MACSTR ")\n", - MAC2STR(hapd->own_addr)); - 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) { - printf("Could not read SSID from system\n"); - 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 || - 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; - memcpy(conf->ssid.ssid, ssid, conf->ssid.ssid_len); - conf->ssid.ssid[conf->ssid.ssid_len] = '\0'; - } - - printf("Using interface %s with hwaddr " MACSTR " and ssid '%s'\n", - hapd->conf->iface, MAC2STR(hapd->own_addr), - hapd->conf->ssid.ssid); - - if (hostapd_setup_wpa_psk(conf)) { - printf("WPA-PSK setup failed.\n"); - return -1; - } - - /* Set flag for whether SSID is broadcast in beacons */ - if (hostapd_set_broadcast_ssid(hapd, - !!hapd->conf->ignore_broadcast_ssid)) { - printf("Could not set broadcast SSID flag for kernel " - "driver\n"); - return -1; - } - - if (hostapd_set_dtim_period(hapd, hapd->conf->dtim_period)) { - printf("Could not set DTIM period for kernel driver\n"); - 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)) { - printf("Could not set SSID for kernel driver\n"); - return -1; - } - - if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MSGDUMPS)) - conf->radius->msg_dumps = 1; - hapd->radius = radius_client_init(hapd, conf->radius); - if (hapd->radius == NULL) { - printf("RADIUS client initialization failed.\n"); - return -1; - } - - if (hostapd_acl_init(hapd)) { - printf("ACL initialization failed.\n"); - return -1; - } - if (ieee802_1x_init(hapd)) { - printf("IEEE 802.1X initialization failed.\n"); - return -1; - } - - if (hapd->conf->wpa) { - 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); - 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_pmk = hostapd_wpa_auth_get_pmk; - cb.set_key = hostapd_wpa_auth_set_key; - cb.get_seqnum = hostapd_wpa_auth_get_seqnum; - cb.get_seqnum_igtk = hostapd_wpa_auth_get_seqnum_igtk; - cb.send_eapol = hostapd_wpa_auth_send_eapol; - cb.for_each_sta = hostapd_wpa_auth_for_each_sta; - hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb); - if (hapd->wpa_auth == NULL) { - printf("WPA initialization failed.\n"); - 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)) { - printf("Initialization of RSN pre-authentication " - "failed.\n"); - return -1; - } - } - - if (accounting_init(hapd)) { - printf("Accounting initialization failed.\n"); - return -1; - } - - if (hapd->conf->ieee802_11f && - (hapd->iapp = iapp_init(hapd, hapd->conf->iapp_iface)) == NULL) { - printf("IEEE 802.11F (IAPP) initialization failed.\n"); - return -1; - } - - if (hostapd_ctrl_iface_init(hapd)) { - printf("Failed to setup control interface\n"); - return -1; - } - - ieee802_11_set_beacon(hapd); - - if (vlan_init(hapd)) { - printf("VLAN initialization failed.\n"); - return -1; - } - - return 0; -} - - -/** - * setup_interface2 - Setup (initialize) an interface (part 2) - * @iface: Pointer to interface data. - * Returns: 0 on success; -1 on failure. - * - * Flushes old stations, sets the channel, DFS parameters, encryption, - * beacons, and WDS links based on the configuration. - */ -static int setup_interface2(struct hostapd_iface *iface) -{ - struct hostapd_data *hapd = iface->bss[0]; - int freq; - size_t j; - int ret = 0; - u8 *prev_addr; - - hostapd_flush_old_stations(hapd); - hostapd_set_privacy(hapd, 0); - - if (hapd->iconf->channel) { - freq = hostapd_hw_get_freq(hapd, hapd->iconf->channel); - printf("Mode: %s Channel: %d Frequency: %d MHz\n", - hostapd_hw_mode_txt(hapd->iconf->hw_mode), - hapd->iconf->channel, freq); - - if (hostapd_set_freq(hapd, hapd->iconf->hw_mode, freq)) { - printf("Could not set channel for kernel driver\n"); - return -1; - } - } - - hostapd_broadcast_wep_clear(hapd); - if (hostapd_setup_encryption(hapd->conf->iface, hapd)) - return -1; - - hostapd_set_beacon_int(hapd, hapd->iconf->beacon_int); - ieee802_11_set_beacon(hapd); - - if (hapd->iconf->rts_threshold > -1 && - hostapd_set_rts(hapd, hapd->iconf->rts_threshold)) { - printf("Could not set RTS threshold for kernel driver\n"); - return -1; - } - - if (hapd->iconf->fragm_threshold > -1 && - hostapd_set_frag(hapd, hapd->iconf->fragm_threshold)) { - printf("Could not set fragmentation threshold for kernel " - "driver\n"); - return -1; - } - - prev_addr = hapd->own_addr; - - for (j = 0; j < iface->num_bss; j++) { - hapd = iface->bss[j]; - if (j) - 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; - } - - ap_list_init(iface); - - if (hostapd_driver_commit(hapd) < 0) { - wpa_printf(MSG_ERROR, "%s: Failed to commit driver " - "configuration", __func__); - return -1; - } - - return ret; -} - - -static void setup_interface_start(void *eloop_data, void *user_ctx); -static void setup_interface2_handler(void *eloop_data, void *user_ctx); - -/** - * setup_interface_finalize - Finish setup interface & call the callback - * @iface: Pointer to interface data. - * @status: Status of the setup interface (0 on success; -1 on failure). - * Returns: 0 on success; -1 on failure (e.g., was not in progress). - */ -static int setup_interface_finalize(struct hostapd_iface *iface, int status) -{ - hostapd_iface_cb cb; - - if (!iface->setup_cb) - return -1; - - eloop_cancel_timeout(setup_interface_start, iface, NULL); - eloop_cancel_timeout(setup_interface2_handler, iface, NULL); - hostapd_select_hw_mode_stop(iface); - - cb = iface->setup_cb; - - iface->setup_cb = NULL; - - cb(iface, status); - - return 0; -} - - -/** - * setup_interface2_wrapper - Wrapper for setup_interface2() - * @iface: Pointer to interface data. - * @status: Status of the hw mode select. - * - * Wrapper for setup_interface2() to calls finalize function upon completion. - */ -static void setup_interface2_wrapper(struct hostapd_iface *iface, int status) -{ - int ret = status; - if (ret) - printf("Could not select hw_mode and channel. (%d)\n", ret); - else - ret = setup_interface2(iface); - - setup_interface_finalize(iface, ret); -} - - -/** - * setup_interface2_handler - Used for immediate call of setup_interface2 - * @eloop_data: Stores the struct hostapd_iface * for the interface. - * @user_ctx: Unused. - */ -static void setup_interface2_handler(void *eloop_data, void *user_ctx) -{ - struct hostapd_iface *iface = eloop_data; - - setup_interface2_wrapper(iface, 0); -} - - -/** - * setup_interface1 - Setup (initialize) an interface (part 1) - * @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. - * Schedules setup_interface2() to be called immediately or after - * hardware mode setup takes place. - */ -static int setup_interface1(struct hostapd_iface *iface) -{ - struct hostapd_data *hapd = iface->bss[0]; - struct hostapd_bss_config *conf = hapd->conf; - size_t i; - char country[4]; - - /* - * Initialize the driver interface and make sure that all BSSes get - * configured with a pointer to this driver interface. - */ - if (hostapd_driver_init(hapd)) { - printf("%s driver initialization failed.\n", - hapd->driver ? hapd->driver->name : "Unknown"); - hapd->driver = NULL; - return -1; - } - for (i = 0; i < iface->num_bss; i++) - iface->bss[i]->driver = hapd->driver; - - if (hostapd_validate_bssid_configuration(iface)) - return -1; - - memcpy(country, hapd->iconf->country, 3); - country[3] = '\0'; - if (hostapd_set_country(hapd, country) < 0) { - printf("Failed to set country code\n"); - return -1; - } - - if (hapd->iconf->ieee80211d || hapd->iconf->ieee80211h) { - if (hostapd_set_ieee80211d(hapd, 1) < 0) { - printf("Failed to set ieee80211d (%d)\n", - hapd->iconf->ieee80211d); - return -1; - } - } - - if (hapd->iconf->bridge_packets != INTERNAL_BRIDGE_DO_NOT_CONTROL && - hostapd_set_internal_bridge(hapd, hapd->iconf->bridge_packets)) { - printf("Failed to set bridge_packets for kernel driver\n"); - return -1; - } - - if (conf->radius_server_clients) { - struct radius_server_conf srv; - memset(&srv, 0, sizeof(srv)); - srv.client_file = conf->radius_server_clients; - srv.auth_port = conf->radius_server_auth_port; - srv.hostapd_conf = conf; - srv.eap_sim_db_priv = hapd->eap_sim_db_priv; - srv.ssl_ctx = hapd->ssl_ctx; - srv.ipv6 = conf->radius_server_ipv6; - hapd->radius_srv = radius_server_init(&srv); - if (hapd->radius_srv == NULL) { - printf("RADIUS server initialization failed.\n"); - return -1; - } - } - - /* TODO: merge with hostapd_driver_init() ? */ - if (hostapd_wireless_event_init(hapd) < 0) - return -1; - - if (hostapd_get_hw_features(iface)) { - /* Not all drivers support this yet, so continue without hw - * feature data. */ - } else { - return hostapd_select_hw_mode_start(iface, - setup_interface2_wrapper); - } - - eloop_register_timeout(0, 0, setup_interface2_handler, iface, NULL); - return 0; -} - - -/** - * setup_interface_start - Handler to start setup interface - * @eloop_data: Stores the struct hostapd_iface * for the interface. - * @user_ctx: Unused. - * - * An eloop handler is used so that all errors can be processed by the - * callback without introducing stack recursion. - */ -static void setup_interface_start(void *eloop_data, void *user_ctx) -{ - struct hostapd_iface *iface = eloop_data; - - int ret; - - ret = setup_interface1(iface); - if (ret) - setup_interface_finalize(iface, ret); -} - - -/** - * hostapd_setup_interface_start - Start the setup of an interface - * @iface: Pointer to interface data. - * @cb: The function to callback when done. - * Returns: 0 if it starts successfully; cb will be called when done. - * -1 on failure; cb will not be called. - * - * Initializes the driver interface, validates the configuration, - * and sets driver parameters based on the configuration. - * Flushes old stations, sets the channel, DFS parameters, encryption, - * beacons, and WDS links based on the configuration. - */ -int hostapd_setup_interface_start(struct hostapd_iface *iface, - hostapd_iface_cb cb) -{ - if (iface->setup_cb) { - wpa_printf(MSG_DEBUG, - "%s: Interface setup already in progress.\n", - iface->bss[0]->conf->iface); - return -1; - } - - iface->setup_cb = cb; - - eloop_register_timeout(0, 0, setup_interface_start, iface, NULL); - - return 0; -} - - -/** - * hostapd_setup_interace_stop - Stops the setup of an interface - * @iface: Pointer to interface data - * Returns: 0 if successfully stopped; - * -1 on failure (i.e., was not in progress) - */ -int hostapd_setup_interface_stop(struct hostapd_iface *iface) -{ - return setup_interface_finalize(iface, -1); -} - - -struct driver { - struct driver *next; - char *name; - const struct driver_ops *ops; -}; -static struct driver *drivers = NULL; - -void driver_register(const char *name, const struct driver_ops *ops) -{ - struct driver *d; - - d = malloc(sizeof(struct driver)); - if (d == NULL) { - printf("Failed to register driver %s!\n", name); - return; - } - d->name = strdup(name); - if (d->name == NULL) { - printf("Failed to register driver %s!\n", name); - free(d); - return; - } - d->ops = ops; - - d->next = drivers; - drivers = d; -} - - -void driver_unregister(const char *name) -{ - struct driver *p, **pp; - - for (pp = &drivers; (p = *pp) != NULL; pp = &p->next) { - if (strcasecmp(p->name, name) == 0) { - *pp = p->next; - p->next = NULL; - free(p->name); - free(p); - break; - } - } -} - - -static void driver_unregister_all(void) -{ - struct driver *p, *pp; - p = drivers; - drivers = NULL; - while (p) { - pp = p; - p = p->next; - free(pp->name); - free(pp); - } -} - - -const struct driver_ops * driver_lookup(const char *name) -{ - struct driver *p; - - if (strcmp(name, "default") == 0) { - p = drivers; - while (p && p->next) - p = p->next; - return p->ops; - } - - for (p = drivers; p != NULL; p = p->next) { - if (strcasecmp(p->name, name) == 0) - return p->ops; - } - - return NULL; -} - - -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-2008, Jouni Malinen <j@w1.fi> " - "and contributors\n"); -} - - -static void usage(void) -{ - show_version(); - fprintf(stderr, - "\n" - "usage: hostapd [-hdBKtv] [-P <PID file>] " - "<configuration file(s)>\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" - " -t include timestamps in some debug messages\n" - " -v show hostapd version\n"); - - exit(1); -} - - -/** - * 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. - */ -static 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 = wpa_zalloc(sizeof(*hapd)); - if (hapd == NULL) - return NULL; - - hapd->iconf = conf; - hapd->conf = bss; - hapd->iface = hapd_iface; - - if (hapd->conf->individual_wep_key_len > 0) { - /* use key0 in individual key and key1 in broadcast key */ - hapd->default_wep_key_idx = 1; - } - -#ifdef EAP_TLS_FUNCS - if (hapd->conf->eap_server && - (hapd->conf->ca_cert || hapd->conf->server_cert)) { - struct tls_connection_params params; - - hapd->ssl_ctx = tls_init(NULL); - if (hapd->ssl_ctx == NULL) { - printf("Failed to initialize TLS\n"); - goto fail; - } - - 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; - - if (tls_global_set_params(hapd->ssl_ctx, ¶ms)) { - printf("Failed to set TLS parameters\n"); - goto fail; - } - - if (tls_global_set_verify(hapd->ssl_ctx, - hapd->conf->check_crl)) { - printf("Failed to enable check_crl\n"); - goto fail; - } - } -#endif /* EAP_TLS_FUNCS */ - -#ifdef EAP_SERVER - 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) { - printf("Failed to initialize EAP-SIM database " - "interface\n"); - goto fail; - } - } -#endif /* EAP_SERVER */ - - if (hapd->conf->assoc_ap) - hapd->assoc_ap_state = WAIT_BEACON; - - /* FIX: need to fix this const vs. not */ - hapd->driver = (struct driver_ops *) hapd->iconf->driver; - - return hapd; - -#if defined(EAP_TLS_FUNCS) || defined(EAP_SERVER) -fail: -#endif - /* TODO: cleanup allocated resources(?) */ - free(hapd); - return NULL; -} - - -/** - * 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 = wpa_zalloc(sizeof(*hapd_iface)); - if (hapd_iface == NULL) - goto fail; - - hapd_iface->config_fname = strdup(config_file); - if (hapd_iface->config_fname == NULL) - goto fail; - - 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 = wpa_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; - } - - return hapd_iface; - -fail: - if (conf) - hostapd_config_free(conf); - if (hapd_iface) { - for (i = 0; hapd_iface->bss && i < hapd_iface->num_bss; i++) { - hapd = hapd_iface->bss[i]; - if (hapd && hapd->ssl_ctx) - tls_deinit(hapd->ssl_ctx); - } - - free(hapd_iface->config_fname); - free(hapd_iface->bss); - free(hapd_iface); - } - return NULL; -} - - -/** - * register_drivers - Register driver interfaces - * - * This function is generated by Makefile (into driver_conf.c) to call all - * configured driver interfaces to register them to core hostapd. - */ -void register_drivers(void); - - -/** - * setup_interface_done - Callback when an interface is done being setup. - * @iface: Pointer to interface data. - * @status: Status of the interface setup (0 on success; -1 on failure). - */ -static void setup_interface_done(struct hostapd_iface *iface, int status) -{ - if (status) { - wpa_printf(MSG_DEBUG, "%s: Unable to setup interface.", - iface->bss[0]->conf->iface); - eloop_terminate(); - } else - wpa_printf(MSG_DEBUG, "%s: Setup of interface done.", - iface->bss[0]->conf->iface); -} - - -int main(int argc, char *argv[]) -{ - struct hapd_interfaces interfaces; - int ret = 1, k; - size_t i, j; - int c, debug = 0, daemonize = 0; - const char *pid_file = NULL; - - for (;;) { - c = getopt(argc, argv, "BdhKP: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 'K': - wpa_debug_show_keys++; - break; - case 'P': - pid_file = optarg; - break; - case 't': - wpa_debug_timestamp++; - break; - case 'v': - show_version(); - exit(1); - break; - - default: - usage(); - break; - } - } - - if (optind == argc) - usage(); - - register_drivers(); /* NB: generated by Makefile */ - - if (eap_server_register_methods()) { - wpa_printf(MSG_ERROR, "Failed to register EAP methods"); - return -1; - } - - interfaces.count = argc - optind; - - interfaces.iface = malloc(interfaces.count * - sizeof(struct hostapd_iface *)); - if (interfaces.iface == NULL) { - printf("malloc failed\n"); - exit(1); - } - - if (eloop_init(&interfaces)) { - wpa_printf(MSG_ERROR, "Failed to initialize event loop"); - return -1; - } - -#ifndef CONFIG_NATIVE_WINDOWS - eloop_register_signal(SIGHUP, handle_reload, NULL); - eloop_register_signal(SIGUSR1, handle_dump_state, NULL); -#endif /* CONFIG_NATIVE_WINDOWS */ - eloop_register_signal_terminate(handle_term, NULL); - - /* Initialize interfaces */ - for (i = 0; i < interfaces.count; i++) { - printf("Configuration file: %s\n", argv[optind + i]); - interfaces.iface[i] = hostapd_init(argv[optind + i]); - if (!interfaces.iface[i]) - goto out; - for (k = 0; k < debug; k++) { - if (interfaces.iface[i]->bss[0]->conf-> - logger_stdout_level > 0) - interfaces.iface[i]->bss[0]->conf-> - logger_stdout_level--; - interfaces.iface[i]->bss[0]->conf->debug++; - } - - ret = hostapd_setup_interface_start(interfaces.iface[i], - setup_interface_done); - if (ret) - goto out; - } - - if (daemonize && os_daemonize(pid_file)) { - perror("daemon"); - goto out; - } - -#ifndef CONFIG_NATIVE_WINDOWS - openlog("hostapd", 0, LOG_DAEMON); -#endif /* CONFIG_NATIVE_WINDOWS */ - - eloop_run(); - - /* Disconnect associated stations from all interfaces and BSSes */ - for (i = 0; i < interfaces.count; i++) { - for (j = 0; j < interfaces.iface[i]->num_bss; j++) { - struct hostapd_data *hapd = - interfaces.iface[i]->bss[j]; - hostapd_free_stas(hapd); - hostapd_flush_old_stations(hapd); - } - } - - ret = 0; - - out: - /* Deinitialize all interfaces */ - for (i = 0; i < interfaces.count; i++) { - if (!interfaces.iface[i]) - continue; - hostapd_setup_interface_stop(interfaces.iface[i]); - hostapd_cleanup_iface_pre(interfaces.iface[i]); - for (j = 0; j < interfaces.iface[i]->num_bss; j++) { - struct hostapd_data *hapd = - interfaces.iface[i]->bss[j]; - hostapd_cleanup(hapd); - if (j == interfaces.iface[i]->num_bss - 1 && - hapd->driver) - hostapd_driver_deinit(hapd); - } - for (j = 0; j < interfaces.iface[i]->num_bss; j++) - free(interfaces.iface[i]->bss[j]); - hostapd_cleanup_iface(interfaces.iface[i]); - } - free(interfaces.iface); - - eloop_destroy(); - -#ifndef CONFIG_NATIVE_WINDOWS - closelog(); -#endif /* CONFIG_NATIVE_WINDOWS */ - - eap_server_unregister_methods(); - - driver_unregister_all(); - - os_daemonize_terminate(pid_file); - - return ret; -} diff --git a/contrib/hostapd/hostapd.conf b/contrib/hostapd/hostapd.conf deleted file mode 100644 index d8ebe164f927..000000000000 --- a/contrib/hostapd/hostapd.conf +++ /dev/null @@ -1,715 +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 driver, an additional configuration parameter, bridge, -# must be used to notify hostapd if the interface is included in a bridge. This -# parameter is not used with Host AP driver. -#bridge=br0 - -# Driver interface type (hostap/wired/madwifi/prism54; default: hostap) -# 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 - -# Debugging: 0 = no, 1 = minimal, 2 = verbose, 3 = msg dumps, 4 = excessive -debug=0 - -# 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. -# Modify as needed to indicate country in which device is operating. -# This can limit available channels and transmit power. -# (default: US) -#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 - -# Enable IEEE 802.11h. This enables the TPC and DFS services when operating -# in a regulatory domain which requires them. Once enabled it will be -# operational only when working in hw_mode a and in countries where it is -# required. The end user should not be allowed to disable this. -# The country_code setting must be configured with the correct country for -# IEEE 802.11h to function. -# When IEEE 802.11h is operational, the channel_policy and configured channel -# settings will be ignored but will behave as though the channel_policy is -# set to "3" (automatic channel selection). When IEEE 802.11h is enabled but -# not operational (for example, if the radio mode is changed from "a" to "b") -# the channel_policy and channel settings take effect again. -# (default: 1 = enabled) -#ieee80211h=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, used with channel_policy=2) -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 <val>' 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 <val>' 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 - -# 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=devicescape, 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) -# default for all these fields: not set, use hardware defaults -# tx_queue_<queue name>_<param> -# 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 -# -# Special queues; normally not user configurable -# -#tx_queue_after_beacon_aifs=2 -#tx_queue_after_beacon_cwmin=15 -#tx_queue_after_beacon_cwmax=1023 -#tx_queue_after_beacon_burst=0 -# -#tx_queue_beacon_aifs=2 -#tx_queue_beacon_cwmin=3 -#tx_queue_beacon_cwmax=7 -#tx_queue_beacon_burst=1.5 - -# 802.1D Tag 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_VI Video -# 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 -# -wme_enabled=1 -# -# Low priority / AC_BK = background -wme_ac_bk_cwmin=4 -wme_ac_bk_cwmax=10 -wme_ac_bk_aifs=7 -wme_ac_bk_txop_limit=0 -wme_ac_bk_acm=0 -# Note: for IEEE 802.11b mode: cWmin=5 cWmax=10 -# -# Normal priority / AC_BE = best effort -wme_ac_be_aifs=3 -wme_ac_be_cwmin=4 -wme_ac_be_cwmax=10 -wme_ac_be_txop_limit=0 -wme_ac_be_acm=0 -# Note: for IEEE 802.11b mode: cWmin=5 cWmax=7 -# -# High priority / AC_VI = video -wme_ac_vi_aifs=2 -wme_ac_vi_cwmin=3 -wme_ac_vi_cwmax=4 -wme_ac_vi_txop_limit=94 -wme_ac_vi_acm=0 -# Note: for IEEE 802.11b mode: cWmin=4 cWmax=5 txop_limit=188 -# -# Highest priority / AC_VO = voice -wme_ac_vo_aifs=2 -wme_ac_vo_cwmin=2 -wme_ac_vo_cwmax=3 -wme_ac_vo_txop_limit=47 -wme_ac_vo_acm=0 -# Note: for IEEE 802.11b mode: cWmin=3 cWmax=4 burst=102 - -# Associate as a station to another AP while still acting as an AP on the same -# channel. -#assoc_ap_addr=00:12:34:56:78:9a - -# 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 - -# Enable/disable internal bridge for packets between associated stations. -# -# When IEEE 802.11 is used in managed mode, packets are usually send through -# the AP even if they are from a wireless station to another wireless station. -# This functionality requires that the AP has a bridge functionality that sends -# frames back to the same interface if their destination is another associated -# station. In addition, broadcast/multicast frames from wireless stations will -# be sent both to the host system net stack (e.g., to eventually wired network) -# and back to the wireless interface. -# -# The internal bridge is implemented within the wireless kernel module and it -# bypasses kernel filtering (netfilter/iptables/ebtables). If direct -# communication between the stations needs to be prevented, the internal -# bridge can be disabled by setting bridge_packets=0. -# -# Note: If this variable is not included in hostapd.conf, hostapd does not -# change the configuration and iwpriv can be used to set the value with -# 'iwpriv wlan# param 10 0' command. If the variable is in hostapd.conf, -# hostapd will override possible iwpriv configuration whenever configuration -# file is reloaded. -# -# default: do not control from hostapd (80211.o defaults to 1=enabled) -#bridge_packets=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 - -# 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 - - -##### 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. -#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. -# 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 authenticator 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. -# (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) -#wpa_pairwise=TKIP 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 - -# 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 is enabled -# 0 = disabled (default) -# 1 = optional -# 2 = required -#ieee80211w=0 - -##### Passive scanning ######################################################## -# Scan different channels every N seconds. 0 = disable passive scanning. -#passive_scan_interval=60 - -# Listen N usecs on each channel when doing passive scanning. -# This value plus the time needed for changing channels should be less than -# 32 milliseconds (i.e. 32000 usec) to avoid interruptions to normal -# operations. Time needed for channel changing varies based on the used wlan -# hardware. -# default: disabled (0) -#passive_scan_listen=10000 - -# Passive scanning mode: -# 0 = scan all supported modes (802.11a/b/g/Turbo) (default) -# 1 = scan only the mode that is currently used for normal operations -#passive_scan_mode=1 - -# Maximum number of entries kept in AP table (either for passive scanning 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! Wi-Fi 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 - -# 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 <MAC addr>). -# -# 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/contrib/hostapd/hostapd.deny b/contrib/hostapd/hostapd.deny deleted file mode 100644 index 1616678f579e..000000000000 --- a/contrib/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/contrib/hostapd/hostapd.eap_user b/contrib/hostapd/hostapd.eap_user deleted file mode 100644 index b9d7f8b08ac6..000000000000 --- a/contrib/hostapd/hostapd.eap_user +++ /dev/null @@ -1,74 +0,0 @@ -# hostapd user database for integrated EAP authenticator - -# 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-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 and EAP-TTLS 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. - -# 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] diff --git a/contrib/hostapd/hostapd.h b/contrib/hostapd/hostapd.h deleted file mode 100644 index 70f802d2a8f0..000000000000 --- a/contrib/hostapd/hostapd.h +++ /dev/null @@ -1,255 +0,0 @@ -/* - * hostapd / Initialization and configuration - * Host AP kernel driver - * Copyright (c) 2002-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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.h" -#include "ap.h" - -#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_PAE -#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ -#endif /* ETH_P_PAE */ - -#ifndef BIT -#define BIT(x) (1 << (x)) -#endif - -#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" -#endif - -#include "config.h" - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -#define MAX_VLAN_ID 4094 - -struct ieee8023_hdr { - u8 dest[6]; - u8 src[6]; - u16 ethertype; -} STRUCT_PACKED; - - -struct ieee80211_hdr { - u16 frame_control; - u16 duration_id; - u8 addr1[6]; - u8 addr2[6]; - u8 addr3[6]; - u16 seq_ctrl; - /* followed by 'u8 addr4[6];' if ToDS and FromDS is set in data frame - */ -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - -#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)) - -/* 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 - -extern unsigned char rfc1042_header[6]; - -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 driver_ops; -struct wpa_ctrl_dst; -struct radius_server_data; - -#ifdef CONFIG_FULL_DYNAMIC_VLAN -struct full_dynamic_vlan; -#endif /* CONFIG_FULL_DYNAMIC_VLAN */ - -/** - * 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 */ - struct sta_info *sta_hash[STA_HASH_SIZE]; - - /* pointers to STA info; based on allocated AID or NULL if AID free - * AID is in the range 1-2007, so sta_aid[0] corresponders to AID 1 - * and so on - */ - struct sta_info *sta_aid[MAX_AID_TABLE_SIZE]; - - struct driver_ops *driver; - - u8 *default_wep_key; - u8 default_wep_key_idx; - - struct radius_client_data *radius; - int radius_client_reconfigured; - u32 acct_session_id_hi, acct_session_id_lo; - - struct iapp_data *iapp; - - enum { DO_NOT_ASSOC = 0, WAIT_BEACON, AUTHENTICATE, ASSOCIATE, - ASSOCIATED } assoc_ap_state; - char assoc_ap_ssid[33]; - int assoc_ap_ssid_len; - u16 assoc_ap_aid; - - struct hostapd_cached_radius_acl *acl_cache; - struct hostapd_acl_query_data *acl_queries; - - struct wpa_authenticator *wpa_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 */ -}; - - -/** - * hostapd_iface_cb - Generic callback type for per-iface asynchronous requests - * @iface: the interface the event occured on. - * @status: 0 if the request succeeded; -1 if the request failed. - */ -typedef void (*hostapd_iface_cb)(struct hostapd_iface *iface, int status); - - -struct hostapd_config_change; - -/** - * struct hostapd_iface - hostapd per-interface data structure - */ -struct hostapd_iface { - char *config_fname; - struct hostapd_config *conf; - - hostapd_iface_cb setup_cb; - - 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; - - 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; - hostapd_iface_cb hw_mode_sel_cb; - - 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 */ - - int dfs_enable; - u8 pwr_const; - unsigned int tx_power; - unsigned int sta_max_power; - - unsigned int channel_switch; - - struct hostapd_config_change *change; - hostapd_iface_cb reload_iface_cb; - hostapd_iface_cb config_reload_cb; -}; - -void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta, - int reassoc); -void hostapd_logger(struct hostapd_data *hapd, const u8 *addr, - unsigned int module, int level, const char *fmt, - ...) PRINTF_FORMAT(5, 6); - - -#ifndef _MSC_VER -#define HOSTAPD_DEBUG(level, args...) \ -do { \ - if (hapd->conf == NULL || hapd->conf->debug >= (level)) \ - printf(args); \ -} while (0) -#endif /* _MSC_VER */ - -#define HOSTAPD_DEBUG_COND(level) (hapd->conf->debug >= (level)) - -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); - -#endif /* HOSTAPD_H */ diff --git a/contrib/hostapd/hostapd.radius_clients b/contrib/hostapd/hostapd.radius_clients deleted file mode 100644 index 3980427253b4..000000000000 --- a/contrib/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/contrib/hostapd/hostapd.sim_db b/contrib/hostapd/hostapd.sim_db deleted file mode 100644 index 01c593de8d2d..000000000000 --- a/contrib/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/contrib/hostapd/hostapd.vlan b/contrib/hostapd/hostapd.vlan deleted file mode 100644 index 98254fa84f01..000000000000 --- a/contrib/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/contrib/hostapd/hostapd.wpa_psk b/contrib/hostapd/hostapd.wpa_psk deleted file mode 100644 index 0a9499acd736..000000000000 --- a/contrib/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/contrib/hostapd/hostapd_cli.1 b/contrib/hostapd/hostapd_cli.1 deleted file mode 100644 index 8d6587fc5c48..000000000000 --- a/contrib/hostapd/hostapd_cli.1 +++ /dev/null @@ -1,83 +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<path>] [-i<ifname>] [-hv] [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> -Path to find control sockets. - -Default: /var/run/hostapd -.TP -.B \-i<ifname> -Interface to listen on. - -Default: first interface found in socket path. -.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 <addr> -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 <debug 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 <j@w1.fi>. -.PP -This manual page was written by Faidon Liambotis <faidon@cube.gr>, -for the Debian project (but may be used by others). diff --git a/contrib/hostapd/hostapd_cli.c b/contrib/hostapd/hostapd_cli.c deleted file mode 100644 index 870f221bb5c3..000000000000 --- a/contrib/hostapd/hostapd_cli.c +++ /dev/null @@ -1,614 +0,0 @@ -/* - * hostapd - command line interface for hostapd daemon - * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 <dirent.h> - -#include "wpa_ctrl.h" -#include "version.h" - - -static const char *hostapd_cli_version = -"hostapd_cli v" VERSION_STR "\n" -"Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi> 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 <addr> get MIB variables for one station\n" -" all_sta get MIB variables for all stations\n" -" new_sta <addr> add a new station\n" -" help show this usage help\n" -" interface [ifname] show interfaces/select interface\n" -" level <debug 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 void usage(void) -{ - fprintf(stderr, "%s\n", hostapd_cli_version); - fprintf(stderr, - "\n" - "usage: hostapd_cli [-p<path>] [-i<ifname>] [-hv] " - "[command..]\n" - "\n" - "Options:\n" - " -h help (show this usage text)\n" - " -v shown version information\n" - " -p<path> path to find control sockets (default: " - "/var/run/hostapd)\n" - " -i<ifname> 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_mib(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_ctrl_command(ctrl, "MIB"); -} - - -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 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'; - snprintf(addr, addr_len, "%s", buf); - 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; -} - - -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 }, - { "sta", hostapd_cli_cmd_sta }, - { "all_sta", hostapd_cli_cmd_all_sta }, - { "new_sta", hostapd_cli_cmd_new_sta }, - { "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 }, - { 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; - 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 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 (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); - printf("> "); - alarm(1); - 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_terminate(int sig) -{ - hostapd_cli_close_connection(); - 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); - alarm(1); -} - - -int main(int argc, char *argv[]) -{ - int interactive; - int warning_displayed = 0; - int c; - - for (;;) { - c = getopt(argc, argv, "hi:p:v"); - if (c < 0) - break; - switch (c) { - case 'h': - usage(); - return 0; - case 'v': - printf("%s\n", hostapd_cli_version); - return 0; - case 'i': - free(ctrl_ifname); - ctrl_ifname = strdup(optarg); - break; - case 'p': - ctrl_iface_dir = optarg; - break; - default: - usage(); - return -1; - } - } - - interactive = argc == optind; - - 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 (strcmp(dent->d_name, ".") == 0 || - strcmp(dent->d_name, "..") == 0) - continue; - printf("Selected interface '%s'\n", - dent->d_name); - ctrl_ifname = 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; - } - sleep(1); - continue; - } - - signal(SIGINT, hostapd_cli_terminate); - signal(SIGTERM, hostapd_cli_terminate); - signal(SIGALRM, hostapd_cli_alarm); - - if (interactive) { - if (wpa_ctrl_attach(ctrl_conn) == 0) { - hostapd_cli_attached = 1; - } else { - printf("Warning: Failed to attach to hostapd.\n"); - } - hostapd_cli_interactive(); - } else - wpa_request(ctrl_conn, argc - optind, &argv[optind]); - - free(ctrl_ifname); - hostapd_cli_close_connection(); - return 0; -} diff --git a/contrib/hostapd/hw_features.c b/contrib/hostapd/hw_features.c deleted file mode 100644 index 484959f63cc5..000000000000 --- a/contrib/hostapd/hw_features.c +++ /dev/null @@ -1,429 +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. - */ - -#include "includes.h" - -#include "hostapd.h" -#include "hw_features.h" -#include "driver.h" -#include "config.h" -#include "ieee802_11.h" -#include "eloop.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++) { - free(hw_features[i].channels); - free(hw_features[i].rates); - } - - 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; - - 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++) { - /* TODO: add regulatory domain lookup */ - unsigned char power_level = 0; - unsigned char antenna_max = 0; - - if ((feature->mode == HOSTAPD_MODE_IEEE80211G || - feature->mode == HOSTAPD_MODE_IEEE80211B) && - feature->channels[j].chan >= 1 && - feature->channels[j].chan <= 11) { - power_level = 20; - feature->channels[j].flag |= - HOSTAPD_CHAN_W_SCAN; - } else - feature->channels[j].flag &= - ~HOSTAPD_CHAN_W_SCAN; - - hostapd_set_channel_flag(hapd, feature->mode, - feature->channels[j].chan, - feature->channels[j].flag, - power_level, - antenna_max); - } - } - - return ret; -} - - -static 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)) { - printf("Failed to update rate sets in kernel module\n"); - } - - free(hapd->iface->current_rates); - hapd->iface->num_rates = 0; - - hapd->iface->current_rates = - malloc(mode->num_rates * sizeof(struct hostapd_rate_data)); - if (!hapd->iface->current_rates) { - printf("Failed to allocate memory for rate table.\n"); - 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].rate)) - continue; - - rate = &hapd->iface->current_rates[hapd->iface->num_rates]; - memcpy(rate, &mode->rates[i], - sizeof(struct hostapd_rate_data)); - if (hostapd_rate_found(basic_rates, rate->rate)) { - rate->flags |= HOSTAPD_RATE_BASIC; - num_basic_rates++; - } else - rate->flags &= ~HOSTAPD_RATE_BASIC; - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "RATE[%d] rate=%d flags=0x%x\n", - hapd->iface->num_rates, rate->rate, rate->flags); - hapd->iface->num_rates++; - } - - if (hapd->iface->num_rates == 0 || num_basic_rates == 0) { - printf("No rates remaining in supported/basic rate sets " - "(%d,%d).\n", hapd->iface->num_rates, num_basic_rates); - return -1; - } - - return 0; -} - - -static void select_hw_mode_start(void *eloop_data, void *user_ctx); -static void select_hw_mode2_handler(void *eloop_data, void *user_ctx); - -/** - * select_hw_mode_finalize - Finish select HW mode & call the callback - * @iface: Pointer to interface data. - * @status: Status of the select HW mode (0 on success; -1 on failure). - * Returns: 0 on success; -1 on failure (e.g., was not in progress). - */ -static int select_hw_mode_finalize(struct hostapd_iface *iface, int status) -{ - hostapd_iface_cb cb; - - if (!iface->hw_mode_sel_cb) - return -1; - - eloop_cancel_timeout(select_hw_mode_start, iface, NULL); - eloop_cancel_timeout(select_hw_mode2_handler, iface, NULL); - - cb = iface->hw_mode_sel_cb; - - iface->hw_mode_sel_cb = NULL; - - cb(iface, status); - - return 0; -} - - -/** - * select_hw_mode2 - Select the hardware mode (part 2) - * @iface: Pointer to interface data. - * @status: Status of auto chanel selection. - * - * Setup the rates and passive scanning based on the configuration. - */ -static void select_hw_mode2(struct hostapd_iface *iface, int status) -{ - int ret = status; - if (ret) - goto fail; - - if (iface->current_mode == NULL) { - hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_WARNING, - "Hardware does not support configured channel"); - ret = -1; - goto fail; - } - - if (hostapd_prepare_rates(iface->bss[0], iface->current_mode)) { - printf("Failed to prepare rates table.\n"); - hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_WARNING, - "Failed to prepare rates table."); - ret = -1; - goto fail; - } - - ret = hostapd_passive_scan(iface->bss[0], 0, - iface->conf->passive_scan_mode, - iface->conf->passive_scan_interval, - iface->conf->passive_scan_listen, - NULL, NULL); - if (ret) { - printf("Could not set passive scanning: %s\n", strerror(ret)); - ret = 0; - } - -fail: - select_hw_mode_finalize(iface, ret); -} - - -/** - * select_hw_mode2_handler - Calls select_hw_mode2 when auto chan isn't used - * @eloop_data: Stores the struct hostapd_iface * for the interface. - * @user_ctx: Unused. - */ -static void select_hw_mode2_handler(void *eloop_data, void *user_ctx) -{ - struct hostapd_iface *iface = eloop_data; - - select_hw_mode2(iface, 0); -} - - -/** - * select_hw_mode1 - Select the hardware mode (part 1) - * @iface: Pointer to interface data. - * Returns: 0 on success; -1 on failure. - * - * Setup the hardware mode and channel based on the configuration. - * Schedules select_hw_mode2() to be called immediately or after automatic - * channel selection takes place. - */ -static int select_hw_mode1(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 == (int) iface->conf->hw_mode) { - iface->current_mode = mode; - break; - } - } - - if (iface->current_mode == NULL) { - printf("Hardware does not support configured mode\n"); - 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_W_SCAN) && - (chan->chan == iface->conf->channel)) { - ok = 1; - break; - } - } - 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; - } - - /* - * Calls select_hw_mode2() via a handler, so that the function is - * always executed from eloop. - */ - eloop_register_timeout(0, 0, select_hw_mode2_handler, iface, NULL); - return 0; -} - - -/** - * select_hw_mode_start - Handler to start select HW mode - * @eloop_data: Stores the struct hostapd_iface * for the interface. - * @user_ctx: Unused. - * - * An eloop handler is used so that all errors can be processed by the - * callback without introducing stack recursion. - */ -static void select_hw_mode_start(void *eloop_data, void *user_ctx) -{ - struct hostapd_iface *iface = (struct hostapd_iface *)eloop_data; - - int ret; - - ret = select_hw_mode1(iface); - if (ret) - select_hw_mode_finalize(iface, ret); -} - - -/** - * hostapd_select_hw_mode_start - Start selection of the hardware mode - * @iface: Pointer to interface data. - * @cb: The function to callback when done. - * Returns: 0 if it starts successfully; cb will be called when done. - * -1 on failure; cb will not be called. - * - * Sets up the hardware mode, channel, rates, and passive scanning - * based on the configuration. - */ -int hostapd_select_hw_mode_start(struct hostapd_iface *iface, - hostapd_iface_cb cb) -{ - if (iface->hw_mode_sel_cb) { - wpa_printf(MSG_DEBUG, - "%s: Hardware mode select already in progress.", - iface->bss[0]->conf->iface); - return -1; - } - - iface->hw_mode_sel_cb = cb; - - eloop_register_timeout(0, 0, select_hw_mode_start, iface, NULL); - - return 0; -} - - -/** - * hostapd_auto_chan_select_stop - Stops automatic channel selection - * @iface: Pointer to interface data. - * Returns: 0 if successfully stopped; - * -1 on failure (i.e., was not in progress) - */ -int hostapd_select_hw_mode_stop(struct hostapd_iface *iface) -{ - return select_hw_mode_finalize(iface, -1); -} - - -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/contrib/hostapd/hw_features.h b/contrib/hostapd/hw_features.h deleted file mode 100644 index 7e5d443432e8..000000000000 --- a/contrib/hostapd/hw_features.h +++ /dev/null @@ -1,61 +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 - -#define HOSTAPD_CHAN_W_SCAN 0x00000001 -#define HOSTAPD_CHAN_W_ACTIVE_SCAN 0x00000002 -#define HOSTAPD_CHAN_W_IBSS 0x00000004 - -struct hostapd_channel_data { - short chan; /* channel number (IEEE 802.11) */ - short freq; /* frequency in MHz */ - int flag; /* flag for hostapd use (HOSTAPD_CHAN_*) */ -}; - -#define HOSTAPD_RATE_ERP 0x00000001 -#define HOSTAPD_RATE_BASIC 0x00000002 -#define HOSTAPD_RATE_PREAMBLE2 0x00000004 -#define HOSTAPD_RATE_SUPPORTED 0x00000010 -#define HOSTAPD_RATE_OFDM 0x00000020 -#define HOSTAPD_RATE_CCK 0x00000040 -#define HOSTAPD_RATE_MANDATORY 0x00000100 - -struct hostapd_rate_data { - int rate; /* rate in 100 kbps */ - int flags; /* HOSTAPD_RATE_ flags */ -}; - -struct hostapd_hw_modes { - int mode; - int num_channels; - struct hostapd_channel_data *channels; - int num_rates; - struct hostapd_rate_data *rates; -}; - - -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_start(struct hostapd_iface *iface, - hostapd_iface_cb cb); -int hostapd_select_hw_mode_stop(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); - -#endif /* HW_FEATURES_H */ diff --git a/contrib/hostapd/iapp.c b/contrib/hostapd/iapp.c deleted file mode 100644 index 5e027fb06bac..000000000000 --- a/contrib/hostapd/iapp.c +++ /dev/null @@ -1,544 +0,0 @@ -/* - * hostapd / IEEE 802.11F-2003 Inter-Access Point Protocol (IAPP) - * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 extenting 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 "includes.h" -#include <net/if.h> -#include <sys/ioctl.h> -#ifdef USE_KERNEL_HEADERS -#include <linux/if_packet.h> -#else /* USE_KERNEL_HEADERS */ -#include <netpacket/packet.h> -#endif /* USE_KERNEL_HEADERS */ - -#include "hostapd.h" -#include "ieee802_11.h" -#include "iapp.h" -#include "eloop.h" -#include "sta_info.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; - u16 identifier; - u16 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]; - u16 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 */ - u16 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; - memcpy(add->mac_addr, mac_addr, ETH_ALEN); - - add->seq_num = host_to_be16(seq_num); - - 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 */ - - memset(msg.da, 0xff, ETH_ALEN); - 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]"); -} - - -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"); - sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_AUTHORIZED); - eloop_cancel_timeout(ap_handle_timer, iapp->hapd, sta); - eloop_register_timeout(0, 0, ap_handle_timer, iapp->hapd, sta); - sta->timeout_next = STA_REMOVE; -} - - -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 = wpa_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; - } - - memset(&ifr, 0, sizeof(ifr)); - strncpy(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); - - 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; - } - - 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; - } - - 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) { - 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); - } - free(iapp); -} - -int iapp_reconfig(struct hostapd_data *hapd, struct hostapd_config *oldconf, - struct hostapd_bss_config *oldbss) -{ - if (hapd->conf->ieee802_11f != oldbss->ieee802_11f || - strcmp(hapd->conf->iapp_iface, oldbss->iapp_iface) != 0) { - - iapp_deinit(hapd->iapp); - hapd->iapp = NULL; - - if (hapd->conf->ieee802_11f) { - hapd->iapp = iapp_init(hapd, hapd->conf->iapp_iface); - - if (hapd->iapp == NULL) - return -1; - } - } - - return 0; -} diff --git a/contrib/hostapd/iapp.h b/contrib/hostapd/iapp.h deleted file mode 100644 index 86de59256043..000000000000 --- a/contrib/hostapd/iapp.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * hostapd / IEEE 802.11F-2003 Inter-Access Point Protocol (IAPP) - * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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); -int iapp_reconfig(struct hostapd_data *hapd, struct hostapd_config *oldconf, - struct hostapd_bss_config *oldbss); - -#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) -{ -} - -static inline int -iapp_reconfig(struct hostapd_data *hapd, struct hostapd_config *oldconf, - struct hostapd_bss_config *oldbss) -{ - return 0; -} - -#endif /* CONFIG_IAPP */ - -#endif /* IAPP_H */ diff --git a/contrib/hostapd/ieee802_11.c b/contrib/hostapd/ieee802_11.c deleted file mode 100644 index 817c30e2ae84..000000000000 --- a/contrib/hostapd/ieee802_11.c +++ /dev/null @@ -1,1636 +0,0 @@ -/* - * hostapd / IEEE 802.11 Management - * Copyright (c) 2002-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 <net/if.h> - -#include "eloop.h" -#include "hostapd.h" -#include "ieee802_11.h" -#include "beacon.h" -#include "hw_features.h" -#include "radius.h" -#include "radius_client.h" -#include "ieee802_11_auth.h" -#include "sta_info.h" -#include "eapol_sm.h" -#include "rc4.h" -#include "ieee802_1x.h" -#include "wpa.h" -#include "wme.h" -#include "ap_list.h" -#include "accounting.h" -#include "driver.h" -#include "ieee802_11h.h" -#include "mlme.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 (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++; - } - - 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 (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++; - } - - 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 && 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; - - if (hapd->iface->dfs_enable) - capab |= WLAN_CAPABILITY_SPECTRUM_MGMT; - - return capab; -} - - -#define OUI_MICROSOFT 0x0050f2 /* Microsoft (also used in Wi-Fi specs) - * 00:50:F2 */ - -static int ieee802_11_parse_vendor_specific(struct hostapd_data *hapd, - 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) { - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MSGDUMPS, "short vendor " - "specific information element ignored " - "(len=%lu)\n", (unsigned long) elen); - } - return -1; - } - - oui = (pos[0] << 16) | (pos[1] << 8) | pos[2]; - 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 WME_OUI_TYPE: /* this is a Wi-Fi WME info. element */ - if (elen < 5) { - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MSGDUMPS, - "short WME information element " - "ignored (len=%lu)\n", - (unsigned long) elen); - return -1; - } - switch (pos[4]) { - case WME_OUI_SUBTYPE_INFORMATION_ELEMENT: - case WME_OUI_SUBTYPE_PARAMETER_ELEMENT: - elems->wme = pos; - elems->wme_len = elen; - break; - case WME_OUI_SUBTYPE_TSPEC_ELEMENT: - elems->wme_tspec = pos; - elems->wme_tspec_len = elen; - break; - default: - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MSGDUMPS, - "unknown WME information element" - " ignored (subtype=%d " - "len=%lu)\n", - pos[4], (unsigned long) elen); - return -1; - } - break; - default: - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MSGDUMPS, - "Unknown Microsoft information element " - "ignored (type=%d len=%lu)\n", - pos[3], (unsigned long) elen); - return -1; - } - break; - - default: - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MSGDUMPS, - "unknown vendor specific information element " - "ignored (vendor OUI %02x:%02x:%02x len=%lu)\n", - pos[0], pos[1], pos[2], (unsigned long) elen); - return -1; - } - - return 0; -} - - -ParseRes ieee802_11_parse_elems(struct hostapd_data *hapd, u8 *start, - size_t len, - struct ieee802_11_elems *elems, - int show_errors) -{ - size_t left = len; - u8 *pos = start; - int unknown = 0; - - memset(elems, 0, sizeof(*elems)); - - while (left >= 2) { - u8 id, elen; - - id = *pos++; - elen = *pos++; - left -= 2; - - if (elen > left) { - if (show_errors) { - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "IEEE 802.11 element parse " - "failed (id=%d elen=%d " - "left=%lu)\n", - 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(hapd, 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; - default: - unknown++; - if (!show_errors) - break; - HOSTAPD_DEBUG(HOSTAPD_DEBUG_EXCESSIVE, - "IEEE 802.11 element parse ignored " - "unknown element (id=%d elen=%d)\n", - id, elen); - break; - } - - left -= elen; - pos += elen; - } - - if (left) - return ParseFailed; - - return unknown ? ParseUnknown : ParseOK; -} - - -void ieee802_11_print_ssid(const u8 *ssid, u8 len) -{ - int i; - for (i = 0; i < len; i++) { - if (ssid[i] >= 32 && ssid[i] < 127) - printf("%c", ssid[i]); - else - printf("<%02x>", ssid[i]); - } -} - - -void ieee802_11_send_deauth(struct hostapd_data *hapd, u8 *addr, u16 reason) -{ - struct ieee80211_mgmt mgmt; - char buf[30]; - - hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "deauthenticate - reason %d", reason); - snprintf(buf, sizeof(buf), "SEND-DEAUTHENTICATE %d", reason); - 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, hapd->own_addr, ETH_ALEN); - memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN); - mgmt.u.deauth.reason_code = host_to_le16(reason); - if (hostapd_send_mgmt_frame(hapd, &mgmt, IEEE80211_HDRLEN + - sizeof(mgmt.u.deauth), 0) < 0) - perror("ieee802_11_send_deauth: send"); -} - - -static void ieee802_11_sta_authenticate(void *eloop_ctx, void *timeout_ctx) -{ - struct hostapd_data *hapd = eloop_ctx; - struct ieee80211_mgmt mgmt; - - if (hapd->assoc_ap_state == WAIT_BEACON) - hapd->assoc_ap_state = AUTHENTICATE; - if (hapd->assoc_ap_state != AUTHENTICATE) - return; - - printf("Authenticate with AP " MACSTR " SSID=", - MAC2STR(hapd->conf->assoc_ap_addr)); - ieee802_11_print_ssid((u8 *) hapd->assoc_ap_ssid, - hapd->assoc_ap_ssid_len); - printf(" (as station)\n"); - - memset(&mgmt, 0, sizeof(mgmt)); - mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_AUTH); - /* Request TX callback */ - mgmt.frame_control |= host_to_le16(BIT(1)); - memcpy(mgmt.da, hapd->conf->assoc_ap_addr, ETH_ALEN); - memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN); - memcpy(mgmt.bssid, hapd->conf->assoc_ap_addr, ETH_ALEN); - mgmt.u.auth.auth_alg = host_to_le16(WLAN_AUTH_OPEN); - mgmt.u.auth.auth_transaction = host_to_le16(1); - mgmt.u.auth.status_code = host_to_le16(0); - if (hostapd_send_mgmt_frame(hapd, &mgmt, IEEE80211_HDRLEN + - sizeof(mgmt.u.auth), 0) < 0) - perror("ieee802_11_sta_authenticate: send"); - - /* Try to authenticate again, if this attempt fails or times out. */ - eloop_register_timeout(5, 0, ieee802_11_sta_authenticate, hapd, NULL); -} - - -static void ieee802_11_sta_associate(void *eloop_ctx, void *timeout_ctx) -{ - struct hostapd_data *hapd = eloop_ctx; - u8 buf[256]; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) buf; - u8 *p; - - if (hapd->assoc_ap_state == AUTHENTICATE) - hapd->assoc_ap_state = ASSOCIATE; - if (hapd->assoc_ap_state != ASSOCIATE) - return; - - printf("Associate with AP " MACSTR " SSID=", - MAC2STR(hapd->conf->assoc_ap_addr)); - ieee802_11_print_ssid((u8 *) hapd->assoc_ap_ssid, - hapd->assoc_ap_ssid_len); - printf(" (as station)\n"); - - memset(mgmt, 0, sizeof(*mgmt)); - mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_ASSOC_REQ); - /* Request TX callback */ - mgmt->frame_control |= host_to_le16(BIT(1)); - memcpy(mgmt->da, hapd->conf->assoc_ap_addr, ETH_ALEN); - memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN); - memcpy(mgmt->bssid, hapd->conf->assoc_ap_addr, ETH_ALEN); - mgmt->u.assoc_req.capab_info = host_to_le16(0); - mgmt->u.assoc_req.listen_interval = host_to_le16(1); - p = &mgmt->u.assoc_req.variable[0]; - - *p++ = WLAN_EID_SSID; - *p++ = hapd->assoc_ap_ssid_len; - memcpy(p, hapd->assoc_ap_ssid, hapd->assoc_ap_ssid_len); - p += hapd->assoc_ap_ssid_len; - - p = hostapd_eid_supp_rates(hapd, p); - p = hostapd_eid_ext_supp_rates(hapd, p); - - if (hostapd_send_mgmt_frame(hapd, mgmt, p - (u8 *) mgmt, 0) < 0) - perror("ieee802_11_sta_associate: send"); - - /* Try to authenticate again, if this attempt fails or times out. */ - eloop_register_timeout(5, 0, ieee802_11_sta_associate, hapd, NULL); -} - - -static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta, - u16 auth_transaction, 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]; - time_t now; - int r; - sta->challenge = wpa_zalloc(WLAN_AUTH_CHALLENGE_LEN); - if (sta->challenge == NULL) - return WLAN_STATUS_UNSPECIFIED_FAILURE; - - now = time(NULL); - r = random(); - memcpy(key, &now, 4); - memcpy(key + 4, &r, 4); - rc4(sta->challenge, WLAN_AUTH_CHALLENGE_LEN, - key, sizeof(key)); - } - return 0; - } - - if (auth_transaction != 3) - return WLAN_STATUS_UNSPECIFIED_FAILURE; - - /* Transaction 3 */ - if (!iswep || !sta->challenge || !challenge || - 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 - free(sta->challenge); - sta->challenge = NULL; - - return 0; -} - - -static void send_auth_reply(struct hostapd_data *hapd, - struct ieee80211_mgmt *mgmt, - u16 auth_alg, u16 auth_transaction, u16 resp, - u8 *challenge) -{ - u8 buf[IEEE80211_HDRLEN + sizeof(mgmt->u.auth) + 2 + - WLAN_AUTH_CHALLENGE_LEN]; - struct ieee80211_mgmt *reply; - size_t rlen; - - memset(buf, 0, sizeof(buf)); - reply = (struct ieee80211_mgmt *) buf; - reply->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_AUTH); - /* Request TX callback */ - reply->frame_control |= host_to_le16(BIT(1)); - memcpy(reply->da, mgmt->sa, ETH_ALEN); - memcpy(reply->sa, hapd->own_addr, ETH_ALEN); - memcpy(reply->bssid, mgmt->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); - rlen = IEEE80211_HDRLEN + sizeof(reply->u.auth); - if (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 2 && - challenge) { - u8 *p = reply->u.auth.variable; - *p++ = WLAN_EID_CHALLENGE; - *p++ = WLAN_AUTH_CHALLENGE_LEN; - memcpy(p, challenge, WLAN_AUTH_CHALLENGE_LEN); - rlen += 2 + WLAN_AUTH_CHALLENGE_LEN; - } else - challenge = NULL; - - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "authentication reply: STA=" MACSTR " auth_alg=%d " - "auth_transaction=%d resp=%d%s\n", - MAC2STR(mgmt->sa), auth_alg, auth_transaction, - resp, challenge ? " challenge" : ""); - if (hostapd_send_mgmt_frame(hapd, reply, rlen, 0) < 0) - perror("send_auth_reply: send"); -} - - -static void handle_auth(struct hostapd_data *hapd, 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; - u8 *challenge = NULL; - u32 session_timeout, acct_interim_interval; - int vlan_id = 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]; - - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "authentication: STA=" MACSTR " auth_alg=%d " - "auth_transaction=%d status_code=%d wep=%d%s\n", - MAC2STR(mgmt->sa), auth_alg, auth_transaction, - status_code, !!(fc & WLAN_FC_ISWEP), - challenge ? " challenge" : ""); - - if (hapd->assoc_ap_state == AUTHENTICATE && auth_transaction == 2 && - memcmp(mgmt->sa, hapd->conf->assoc_ap_addr, ETH_ALEN) == 0 && - memcmp(mgmt->bssid, hapd->conf->assoc_ap_addr, ETH_ALEN) == 0) { - if (status_code != 0) { - printf("Authentication (as station) with AP " - MACSTR " failed (status_code=%d)\n", - MAC2STR(hapd->conf->assoc_ap_addr), - status_code); - return; - } - printf("Authenticated (as station) with AP " MACSTR "\n", - MAC2STR(hapd->conf->assoc_ap_addr)); - ieee802_11_sta_associate(hapd, NULL); - return; - } - - if (hapd->tkip_countermeasures) { - resp = WLAN_REASON_MICHAEL_MIC_FAILURE; - goto fail; - } - - if (!(((hapd->conf->auth_algs & HOSTAPD_AUTH_OPEN) && - auth_alg == WLAN_AUTH_OPEN) || - ((hapd->conf->auth_algs & HOSTAPD_AUTH_SHARED_KEY) && - 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 (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) { - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Authentication frame " - "from " MACSTR " waiting for an external " - "authentication\n", 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, - sta->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->radius->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); - break; - } - - fail: - send_auth_reply(hapd, mgmt, auth_alg, auth_transaction + 1, resp, - sta ? sta->challenge : NULL); -} - - -static void handle_assoc(struct hostapd_data *hapd, - struct ieee80211_mgmt *mgmt, size_t len, int reassoc) -{ - u16 capab_info, listen_interval; - u16 resp = WLAN_STATUS_SUCCESS; - u8 *pos, *wpa_ie; - size_t wpa_ie_len; - int send_deauth = 0, send_len, left, i; - struct sta_info *sta; - struct ieee802_11_elems elems; - - 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); - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "reassociation request: STA=" MACSTR - " capab_info=0x%02x " - "listen_interval=%d current_ap=" MACSTR "\n", - 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); - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "association request: STA=" MACSTR - " capab_info=0x%02x listen_interval=%d\n", - 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); - if (sta == NULL || (sta->flags & WLAN_STA_AUTH) == 0) { - printf("STA " MACSTR " trying to associate before " - "authentication\n", MAC2STR(mgmt->sa)); - if (sta) { - printf(" sta: addr=" MACSTR " aid=%d flags=0x%04x\n", - MAC2STR(sta->addr), sta->aid, sta->flags); - } - send_deauth = 1; - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - - if (hapd->tkip_countermeasures) { - resp = WLAN_REASON_MICHAEL_MIC_FAILURE; - goto fail; - } - - if (reassoc) { - memcpy(sta->previous_ap, mgmt->u.reassoc_req.current_ap, - ETH_ALEN); - } - - sta->capability = capab_info; - - /* followed by SSID and Supported rates */ - if (ieee802_11_parse_elems(hapd, pos, left, &elems, 1) == ParseFailed - || !elems.ssid) { - printf("STA " MACSTR " sent invalid association request\n", - MAC2STR(sta->addr)); - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - - if (elems.ssid_len != hapd->conf->ssid.ssid_len || - memcmp(elems.ssid, hapd->conf->ssid.ssid, elems.ssid_len) != 0) { - printf("Station " MACSTR " tried to associate with " - "unknown SSID '", MAC2STR(sta->addr)); - ieee802_11_print_ssid(elems.ssid, elems.ssid_len); - printf("'\n"); - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - - sta->flags &= ~WLAN_STA_WME; - if (elems.wme && hapd->conf->wme_enabled) { - if (hostapd_eid_wme_valid(hapd, elems.wme, elems.wme_len)) - hostapd_logger(hapd, sta->addr, - HOSTAPD_MODULE_WPA, - HOSTAPD_LEVEL_DEBUG, - "invalid WME element in association " - "request"); - else - sta->flags |= WLAN_STA_WME; - } - - if (!elems.supp_rates) { - hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "No supported rates element in AssocReq"); - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - - if (elems.supp_rates_len > sizeof(sta->supported_rates)) { - hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "Invalid supported rates element length %d", - elems.supp_rates_len); - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - - memset(sta->supported_rates, 0, sizeof(sta->supported_rates)); - 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, mgmt->sa, - HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "Invalid supported rates element length" - " %d+%d", elems.supp_rates_len, - elems.ext_supp_rates_len); - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - - 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; - } - - if ((hapd->conf->wpa & HOSTAPD_WPA_VERSION_WPA2) && elems.rsn_ie) { - wpa_ie = elems.rsn_ie; - wpa_ie_len = elems.rsn_ie_len; - } else if ((hapd->conf->wpa & HOSTAPD_WPA_VERSION_WPA) && - elems.wpa_ie) { - wpa_ie = elems.wpa_ie; - wpa_ie_len = elems.wpa_ie_len; - } else { - wpa_ie = NULL; - wpa_ie_len = 0; - } - if (hapd->conf->wpa && wpa_ie == NULL) { - printf("STA " MACSTR ": No WPA/RSN IE in association " - "request\n", MAC2STR(sta->addr)); - resp = WLAN_STATUS_INVALID_IE; - goto fail; - } - - if (hapd->conf->wpa) { - 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) { - printf("Failed to initialize WPA state machine\n"); - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, - wpa_ie, wpa_ie_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_UNSPECIFIED_FAILURE; /* FIX */ - else if (res == WPA_INVALID_MGMT_GROUP_CIPHER) - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; /* FIX */ -#endif /* CONFIG_IEEE80211W */ - else if (res != WPA_IE_OK) - resp = WLAN_STATUS_INVALID_IE; - if (resp != WLAN_STATUS_SUCCESS) - goto fail; - } - - if (hapd->iface->dfs_enable && - hapd->iconf->ieee80211h == SPECT_STRICT_BINDING) { - if (hostapd_check_power_cap(hapd, elems.power_cap, - elems.power_cap_len)) { - resp = WLAN_STATUS_PWR_CAPABILITY_NOT_VALID; - hostapd_logger(hapd, sta->addr, - HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "Power capabilities of the station not " - "acceptable"); - goto fail; - } - } - - 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); - } - - /* get a unique AID */ - if (sta->aid > 0) { - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - " old AID %d\n", sta->aid); - } else { - for (sta->aid = 1; sta->aid <= MAX_AID_TABLE_SIZE; sta->aid++) - if (hapd->sta_aid[sta->aid - 1] == NULL) - break; - if (sta->aid > MAX_AID_TABLE_SIZE) { - sta->aid = 0; - resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; - printf(" no room for more AIDs\n"); - goto fail; - } else { - hapd->sta_aid[sta->aid - 1] = sta; - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - " new AID %d\n", sta->aid); - } - } - - 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 - */ - - if (sta->last_assoc_req) - free(sta->last_assoc_req); - sta->last_assoc_req = (struct ieee80211_mgmt *) malloc(len); - if (sta->last_assoc_req) - 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: - - /* use the queued buffer for transmission because it is large enough - * and not needed anymore */ - mgmt->frame_control = - IEEE80211_FC(WLAN_FC_TYPE_MGMT, - (send_deauth ? WLAN_FC_STYPE_DEAUTH : - (reassoc ? WLAN_FC_STYPE_REASSOC_RESP : - WLAN_FC_STYPE_ASSOC_RESP))); - memcpy(mgmt->da, mgmt->sa, ETH_ALEN); - memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN); - /* Addr3 = BSSID - already set */ - - send_len = IEEE80211_HDRLEN; - if (send_deauth) { - send_len += sizeof(mgmt->u.deauth); - mgmt->u.deauth.reason_code = host_to_le16(resp); - } else { - u8 *p; - send_len += sizeof(mgmt->u.assoc_resp); - mgmt->u.assoc_resp.capab_info = - host_to_le16(hostapd_own_capab_info(hapd, sta, 0)); - mgmt->u.assoc_resp.status_code = host_to_le16(resp); - mgmt->u.assoc_resp.aid = host_to_le16((sta ? sta->aid : 0) - | BIT(14) | BIT(15)); - /* Supported rates */ - p = hostapd_eid_supp_rates(hapd, mgmt->u.assoc_resp.variable); - /* Extended supported rates */ - p = hostapd_eid_ext_supp_rates(hapd, p); - if (sta->flags & WLAN_STA_WME) - p = hostapd_eid_wme(hapd, p); - send_len += p - mgmt->u.assoc_resp.variable; - - /* Request TX callback */ - mgmt->frame_control |= host_to_le16(BIT(1)); - } - - if (hostapd_send_mgmt_frame(hapd, mgmt, send_len, 0) < 0) - perror("handle_assoc: send"); -} - - -static void handle_assoc_resp(struct hostapd_data *hapd, - struct ieee80211_mgmt *mgmt, size_t len) -{ - u16 status_code, aid; - - if (hapd->assoc_ap_state != ASSOCIATE) { - printf("Unexpected association response received from " MACSTR - "\n", MAC2STR(mgmt->sa)); - return; - } - - if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.assoc_resp)) { - printf("handle_assoc_resp - too short payload (len=%lu)\n", - (unsigned long) len); - return; - } - - if (memcmp(mgmt->sa, hapd->conf->assoc_ap_addr, ETH_ALEN) != 0 || - memcmp(mgmt->bssid, hapd->conf->assoc_ap_addr, ETH_ALEN) != 0) { - printf("Received association response from unexpected address " - "(SA=" MACSTR " BSSID=" MACSTR "\n", - MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid)); - return; - } - - status_code = le_to_host16(mgmt->u.assoc_resp.status_code); - aid = le_to_host16(mgmt->u.assoc_resp.aid); - aid &= ~(BIT(14) | BIT(15)); - - if (status_code != 0) { - printf("Association (as station) with AP " MACSTR " failed " - "(status_code=%d)\n", - MAC2STR(hapd->conf->assoc_ap_addr), status_code); - /* Try to authenticate again */ - hapd->assoc_ap_state = AUTHENTICATE; - eloop_register_timeout(5, 0, ieee802_11_sta_authenticate, - hapd, NULL); - } - - printf("Associated (as station) with AP " MACSTR " (aid=%d)\n", - MAC2STR(hapd->conf->assoc_ap_addr), aid); - hapd->assoc_ap_aid = aid; - hapd->assoc_ap_state = ASSOCIATED; - - if (hostapd_set_assoc_ap(hapd, hapd->conf->assoc_ap_addr)) { - printf("Could not set associated AP address to kernel " - "driver.\n"); - } -} - - -static void handle_disassoc(struct hostapd_data *hapd, - 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; - } - - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "disassocation: STA=" MACSTR " reason_code=%d\n", - MAC2STR(mgmt->sa), - le_to_host16(mgmt->u.disassoc.reason_code)); - - if (hapd->assoc_ap_state != DO_NOT_ASSOC && - memcmp(mgmt->sa, hapd->conf->assoc_ap_addr, ETH_ALEN) == 0) { - printf("Assoc AP " MACSTR " sent disassociation " - "(reason_code=%d) - try to authenticate\n", - MAC2STR(hapd->conf->assoc_ap_addr), - le_to_host16(mgmt->u.disassoc.reason_code)); - hapd->assoc_ap_state = AUTHENTICATE; - ieee802_11_sta_authenticate(hapd, NULL); - eloop_register_timeout(0, 500000, ieee802_11_sta_authenticate, - hapd, NULL); - return; - } - - 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; - 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_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, - struct ieee80211_mgmt *mgmt, size_t len) -{ - struct sta_info *sta; - - if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.deauth)) { - printf("handle_deauth - too short payload (len=%lu)\n", - (unsigned long) len); - return; - } - - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "deauthentication: STA=" MACSTR " reason_code=%d\n", - MAC2STR(mgmt->sa), - le_to_host16(mgmt->u.deauth.reason_code)); - - if (hapd->assoc_ap_state != DO_NOT_ASSOC && - memcmp(mgmt->sa, hapd->conf->assoc_ap_addr, ETH_ALEN) == 0) { - printf("Assoc AP " MACSTR " sent deauthentication " - "(reason_code=%d) - try to authenticate\n", - MAC2STR(hapd->conf->assoc_ap_addr), - le_to_host16(mgmt->u.deauth.reason_code)); - hapd->assoc_ap_state = AUTHENTICATE; - eloop_register_timeout(0, 500000, ieee802_11_sta_authenticate, - hapd, NULL); - return; - } - - sta = ap_get_sta(hapd, mgmt->sa); - if (sta == NULL) { - printf("Station " MACSTR " trying to deauthenticate, but it " - "is not authenticated.\n", MAC2STR(mgmt->sa)); - return; - } - - sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); - 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, - 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(hapd, mgmt->u.beacon.variable, - len - (IEEE80211_HDRLEN + - sizeof(mgmt->u.beacon)), &elems, - 0); - - if (hapd->assoc_ap_state == WAIT_BEACON && - memcmp(mgmt->sa, hapd->conf->assoc_ap_addr, ETH_ALEN) == 0) { - if (elems.ssid && elems.ssid_len <= 32) { - memcpy(hapd->assoc_ap_ssid, elems.ssid, - elems.ssid_len); - hapd->assoc_ap_ssid[elems.ssid_len] = '\0'; - hapd->assoc_ap_ssid_len = elems.ssid_len; - } - ieee802_11_sta_authenticate(hapd, NULL); - } - - ap_list_process_beacon(hapd->iface, mgmt, &elems, fi); - - if (!HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_EXCESSIVE)) - return; - - printf("Beacon from " MACSTR, MAC2STR(mgmt->sa)); - if (elems.ssid) { - printf(" SSID='"); - ieee802_11_print_ssid(elems.ssid, elems.ssid_len); - printf("'"); - } - if (elems.ds_params && elems.ds_params_len == 1) - printf(" CHAN=%d", elems.ds_params[0]); - printf("\n"); -} - - -static void handle_action(struct hostapd_data *hapd, - struct ieee80211_mgmt *mgmt, size_t len) -{ - 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; - } - - switch (mgmt->u.action.category) { - case WME_ACTION_CATEGORY: - hostapd_wme_action(hapd, mgmt, len); - return; - } - - hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "handle_action - unknown action category %d", - mgmt->u.action.category); - if (!(mgmt->da[0] & 0x01) && !(mgmt->u.action.category & 0x80) && - !(mgmt->sa[0] & 0x01)) { - /* - * 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"); - os_memcpy(mgmt->da, mgmt->sa, ETH_ALEN); - os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN); - os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN); - mgmt->u.action.category |= 0x80; - - hostapd_send_mgmt_frame(hapd, mgmt, len, 0); - } -} - - -/** - * 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 - * @stype: management frame subtype from frame control field - * - * 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, u8 *buf, size_t len, u16 stype, - struct hostapd_frame_info *fi) -{ - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) buf; - int broadcast; - - if (stype == WLAN_FC_STYPE_BEACON) { - HOSTAPD_DEBUG(HOSTAPD_DEBUG_EXCESSIVE, "mgmt::beacon\n"); - handle_beacon(hapd, mgmt, len, fi); - return; - } - - if (fi && fi->passive_scan) - 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 && memcmp(mgmt->bssid, hapd->own_addr, ETH_ALEN) != 0 && - (hapd->assoc_ap_state == DO_NOT_ASSOC || - memcmp(mgmt->bssid, hapd->conf->assoc_ap_addr, ETH_ALEN) != 0)) { - printf("MGMT: BSSID=" MACSTR " not our address\n", - MAC2STR(mgmt->bssid)); - return; - } - - - if (stype == WLAN_FC_STYPE_PROBE_REQ) { - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MSGDUMPS, "mgmt::probe_req\n"); - handle_probe_req(hapd, mgmt, len); - return; - } - - if (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: - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "mgmt::auth\n"); - handle_auth(hapd, mgmt, len); - break; - case WLAN_FC_STYPE_ASSOC_REQ: - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "mgmt::assoc_req\n"); - handle_assoc(hapd, mgmt, len, 0); - break; - case WLAN_FC_STYPE_ASSOC_RESP: - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "mgmt::assoc_resp\n"); - handle_assoc_resp(hapd, mgmt, len); - break; - case WLAN_FC_STYPE_REASSOC_REQ: - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "mgmt::reassoc_req\n"); - handle_assoc(hapd, mgmt, len, 1); - break; - case WLAN_FC_STYPE_DISASSOC: - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "mgmt::disassoc\n"); - handle_disassoc(hapd, mgmt, len); - break; - case WLAN_FC_STYPE_DEAUTH: - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "mgmt::deauth\n"); - handle_deauth(hapd, mgmt, len); - break; - case WLAN_FC_STYPE_ACTION: - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "mgmt::action\n"); - 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, - 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, - struct ieee80211_mgmt *mgmt, - size_t len, int reassoc, int ok) -{ - u16 status; - struct sta_info *sta; - int new_assoc = 1; - - 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); - accounting_sta_get_id(hapd, sta); - - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, - "associated (aid %d, accounting session %08X-%08X)", - sta->aid, sta->acct_session_id_hi, - sta->acct_session_id_lo); - - if (sta->flags & WLAN_STA_ASSOC) - new_assoc = 0; - sta->flags |= WLAN_STA_ASSOC; - - if (reassoc) - mlme_reassociate_indication(hapd, sta); - else - mlme_associate_indication(hapd, sta); - - if (hostapd_sta_add(hapd->conf->iface, hapd, sta->addr, sta->aid, - sta->capability, sta->supported_rates, - sta->supported_rates_len, 0)) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_NOTICE, - "Could not add STA to kernel driver"); - } - - 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. - */ - ap_sta_bind_vlan(hapd, sta, 0); - } else if (sta->vlan_id) { - /* VLAN ID already set (e.g., by PMKSA caching), so bind STA */ - ap_sta_bind_vlan(hapd, sta, 0); - } - if (sta->flags & WLAN_STA_SHORT_PREAMBLE) { - hostapd_sta_set_flags(hapd, sta->addr, - WLAN_STA_SHORT_PREAMBLE, ~0); - } else { - hostapd_sta_set_flags(hapd, sta->addr, - 0, ~WLAN_STA_SHORT_PREAMBLE); - } - - 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); - - fail: - /* Copy of the association request is not needed anymore */ - if (sta->last_assoc_req) { - free(sta->last_assoc_req); - sta->last_assoc_req = NULL; - } -} - - -void ieee802_11_mgmt_cb(struct hostapd_data *hapd, u8 *buf, size_t len, - u16 stype, int ok) -{ - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) buf; - - switch (stype) { - case WLAN_FC_STYPE_AUTH: - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "mgmt::auth cb\n"); - handle_auth_cb(hapd, mgmt, len, ok); - break; - case WLAN_FC_STYPE_ASSOC_RESP: - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "mgmt::assoc_resp cb\n"); - handle_assoc_cb(hapd, mgmt, len, 0, ok); - break; - case WLAN_FC_STYPE_REASSOC_RESP: - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "mgmt::reassoc_resp cb\n"); - handle_assoc_cb(hapd, mgmt, len, 1, ok); - break; - case WLAN_FC_STYPE_PROBE_RESP: - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "mgmt::proberesp cb\n"); - break; - default: - printf("unknown mgmt cb frame subtype %d\n", stype); - break; - } -} - - -static void ieee80211_tkip_countermeasures_stop(void *eloop_ctx, - void *timeout_ctx) -{ - struct hostapd_data *hapd = eloop_ctx; - hapd->tkip_countermeasures = 0; - hostapd_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_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_sta_deauth(hapd, sta->addr, - WLAN_REASON_MICHAEL_MIC_FAILURE); - sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | - WLAN_STA_AUTHORIZED); - hostapd_sta_remove(hapd, sta->addr); - } -} - - -void ieee80211_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 { - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "MLME-MICHAELMICFAILURE.indication " - "for not associated STA (" MACSTR - ") ignored\n", 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; -} - - -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; -} - -#endif /* CONFIG_NATIVE_WINDOWS */ diff --git a/contrib/hostapd/ieee802_11.h b/contrib/hostapd/ieee802_11.h deleted file mode 100644 index 37bd711d0194..000000000000 --- a/contrib/hostapd/ieee802_11.h +++ /dev/null @@ -1,333 +0,0 @@ -/* - * hostapd / IEEE 802.11 Management - * Copyright (c) 2002-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 - -/* IEEE 802.11 defines */ - -#define WLAN_FC_PVER (BIT(1) | BIT(0)) -#define WLAN_FC_TODS BIT(8) -#define WLAN_FC_FROMDS BIT(9) -#define WLAN_FC_MOREFRAG BIT(10) -#define WLAN_FC_RETRY BIT(11) -#define WLAN_FC_PWRMGT BIT(12) -#define WLAN_FC_MOREDATA BIT(13) -#define WLAN_FC_ISWEP BIT(14) -#define WLAN_FC_ORDER BIT(15) - -#define WLAN_FC_GET_TYPE(fc) (((fc) & (BIT(3) | BIT(2))) >> 2) -#define WLAN_FC_GET_STYPE(fc) \ - (((fc) & (BIT(7) | BIT(6) | BIT(5) | BIT(4))) >> 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 - -/* Authentication algorithms */ -#define WLAN_AUTH_OPEN 0 -#define WLAN_AUTH_SHARED_KEY 1 - -#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 */ -#define WLAN_STATUS_SUCCESS 0 -#define WLAN_STATUS_UNSPECIFIED_FAILURE 1 -#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.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 - -/* Reason codes */ -#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.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 - - -/* 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_RSN 48 -#define WLAN_EID_EXT_SUPP_RATES 50 -#define WLAN_EID_GENERIC 221 -#define WLAN_EID_VENDOR_SPECIFIC 221 - - -struct ieee80211_mgmt { - u16 frame_control; - u16 duration; - u8 da[6]; - u8 sa[6]; - u8 bssid[6]; - u16 seq_ctrl; - union { - struct { - u16 auth_alg; - u16 auth_transaction; - u16 status_code; - /* possibly followed by Challenge text */ - u8 variable[0]; - } __attribute__ ((packed)) auth; - struct { - u16 reason_code; - } __attribute__ ((packed)) deauth; - struct { - u16 capab_info; - u16 listen_interval; - /* followed by SSID and Supported rates */ - u8 variable[0]; - } __attribute__ ((packed)) assoc_req; - struct { - u16 capab_info; - u16 status_code; - u16 aid; - /* followed by Supported rates */ - u8 variable[0]; - } __attribute__ ((packed)) assoc_resp, reassoc_resp; - struct { - u16 capab_info; - u16 listen_interval; - u8 current_ap[6]; - /* followed by SSID and Supported rates */ - u8 variable[0]; - } __attribute__ ((packed)) reassoc_req; - struct { - u16 reason_code; - } __attribute__ ((packed)) disassoc; - struct { - /* only variable items: SSID, Supported rates */ - u8 variable[0]; - } __attribute__ ((packed)) probe_req; - struct { - u8 timestamp[8]; - u16 beacon_int; - u16 capab_info; - /* followed by some of SSID, Supported rates, - * FH Params, DS Params, CF Params, IBSS Params */ - u8 variable[0]; - } __attribute__ ((packed)) probe_resp; - struct { - u8 timestamp[8]; - u16 beacon_int; - u16 capab_info; - /* followed by some of SSID, Supported rates, - * FH Params, DS Params, CF Params, IBSS Params, TIM */ - u8 variable[0]; - } __attribute__ ((packed)) beacon; - struct { - u8 category; - union { - struct { - u8 action_code; - u8 dialog_token; - u8 status_code; - u8 variable[0]; - } __attribute__ ((packed)) wme_action; - struct{ - u8 action_code; - u8 element_id; - u8 length; - u8 switch_mode; - u8 new_chan; - u8 switch_count; - } __attribute__ ((packed)) chan_switch; - } u; - } __attribute__ ((packed)) action; - } u; -} __attribute__ ((packed)); - - -#define ERP_INFO_NON_ERP_PRESENT BIT(0) -#define ERP_INFO_USE_PROTECTION BIT(1) -#define ERP_INFO_BARKER_PREAMBLE_MODE BIT(2) - -/* Parsed Information Elements */ -struct ieee802_11_elems { - u8 *ssid; - u8 ssid_len; - u8 *supp_rates; - u8 supp_rates_len; - u8 *fh_params; - u8 fh_params_len; - u8 *ds_params; - u8 ds_params_len; - u8 *cf_params; - u8 cf_params_len; - u8 *tim; - u8 tim_len; - u8 *ibss_params; - u8 ibss_params_len; - u8 *challenge; - u8 challenge_len; - u8 *erp_info; - u8 erp_info_len; - u8 *ext_supp_rates; - u8 ext_supp_rates_len; - u8 *wpa_ie; - u8 wpa_ie_len; - u8 *rsn_ie; - u8 rsn_ie_len; - u8 *wme; - u8 wme_len; - u8 *wme_tspec; - u8 wme_tspec_len; - u8 *power_cap; - u8 power_cap_len; - u8 *supp_channels; - u8 supp_channels_len; -}; - -typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes; - - -struct hostapd_frame_info { - u32 phytype; - u32 channel; - u32 datarate; - u32 ssi_signal; - - unsigned int passive_scan:1; -}; - - -void ieee802_11_send_deauth(struct hostapd_data *hapd, u8 *addr, u16 reason); -void ieee802_11_mgmt(struct hostapd_data *hapd, u8 *buf, size_t len, - u16 stype, struct hostapd_frame_info *fi); -void ieee802_11_mgmt_cb(struct hostapd_data *hapd, u8 *buf, size_t len, - u16 stype, int ok); -ParseRes ieee802_11_parse_elems(struct hostapd_data *hapd, u8 *start, - size_t len, - struct ieee802_11_elems *elems, - int show_errors); -void ieee802_11_print_ssid(const u8 *ssid, u8 len); -void ieee80211_michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, - int local); -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); -u16 hostapd_own_capab_info(struct hostapd_data *hapd, struct sta_info *sta, - int probe); -u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid); -u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid); - -#endif /* IEEE802_11_H */ diff --git a/contrib/hostapd/ieee802_11_auth.c b/contrib/hostapd/ieee802_11_auth.c deleted file mode 100644 index 75d0494e3c0c..000000000000 --- a/contrib/hostapd/ieee802_11_auth.c +++ /dev/null @@ -1,485 +0,0 @@ -/* - * hostapd / IEEE 802.11 authentication (ACL) - * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "hostapd.h" -#include "ieee802_11.h" -#include "ieee802_11_auth.h" -#include "radius.h" -#include "radius_client.h" -#include "eloop.h" -#include "driver.h" - -#define RADIUS_ACL_TIMEOUT 30 - - -struct hostapd_cached_radius_acl { - 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 { - 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; -}; - - -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; - 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; - time_t now; - - time(&now); - entry = hapd->acl_cache; - - while (entry) { - if (memcmp(entry->addr, addr, ETH_ALEN) == 0) { - if (now - 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; -} - - -static void hostapd_acl_query_free(struct hostapd_acl_query_data *query) -{ - if (query == NULL) - return; - free(query->auth_msg); - free(query); -} - - -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); - - snprintf(buf, sizeof(buf), RADIUS_ADDR_FORMAT, MAC2STR(addr)); - if (!radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, (u8 *) buf, - strlen(buf))) { - printf("Could not add User-Name\n"); - goto fail; - } - - if (!radius_msg_add_attr_user_password( - msg, (u8 *) buf, strlen(buf), - hapd->conf->radius->auth_server->shared_secret, - hapd->conf->radius->auth_server->shared_secret_len)) { - printf("Could not add User-Password\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, - strlen(hapd->conf->nas_identifier))) { - printf("Could not add NAS-Identifier\n"); - goto fail; - } - - 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, strlen(buf))) { - printf("Could not add Called-Station-Id\n"); - goto fail; - } - - snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT, - MAC2STR(addr)); - if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID, - (u8 *) buf, 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; - } - - snprintf(buf, sizeof(buf), "CONNECT 11Mbps 802.11b"); - if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO, - (u8 *) buf, strlen(buf))) { - printf("Could not add Connect-Info\n"); - goto fail; - } - - radius_client_send(hapd->radius, msg, RADIUS_AUTH, addr); - return 0; - - fail: - radius_msg_free(msg); - free(msg); - return -1; -} - - -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)) - return HOSTAPD_ACL_ACCEPT; - - if (hostapd_maclist_found(hapd->conf->deny_mac, - hapd->conf->num_deny_mac, addr)) - 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) { - 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 (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 = wpa_zalloc(sizeof(*query)); - if (query == NULL) { - printf("malloc for query data failed\n"); - return HOSTAPD_ACL_REJECT; - } - time(&query->timestamp); - memcpy(query->addr, addr, ETH_ALEN); - if (hostapd_radius_acl_query(hapd, addr, query)) { - printf("Failed to send Access-Request for ACL " - "query.\n"); - hostapd_acl_query_free(query); - return HOSTAPD_ACL_REJECT; - } - - query->auth_msg = malloc(len); - if (query->auth_msg == NULL) { - printf("Failed to allocate memory for auth frame.\n"); - hostapd_acl_query_free(query); - return HOSTAPD_ACL_REJECT; - } - 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; - } - - return HOSTAPD_ACL_REJECT; -} - - -static void hostapd_acl_expire_cache(struct hostapd_data *hapd, 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) { - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "Cached ACL entry for " MACSTR - " has expired.\n", MAC2STR(entry->addr)); - if (prev) - prev->next = entry->next; - else - hapd->acl_cache = entry->next; -#ifdef CONFIG_DRIVER_RADIUS_ACL - hostapd_set_radius_acl_expire(hapd, entry->addr); -#endif - tmp = entry; - entry = entry->next; - free(tmp); - continue; - } - - prev = entry; - entry = entry->next; - } -} - - -static void hostapd_acl_expire_queries(struct hostapd_data *hapd, 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) { - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "ACL query for " MACSTR - " has expired.\n", 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; - } -} - - -static void hostapd_acl_expire(void *eloop_ctx, void *timeout_ctx) -{ - struct hostapd_data *hapd = eloop_ctx; - time_t now; - - time(&now); - hostapd_acl_expire_cache(hapd, now); - hostapd_acl_expire_queries(hapd, now); - - eloop_register_timeout(10, 0, hostapd_acl_expire, hapd, NULL); -} - - -/* Return 0 if RADIUS message was a reply to ACL query (and was processed here) - * or -1 if not. */ -static RadiusRxResult -hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req, - 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; - - query = hapd->acl_queries; - prev = NULL; - while (query) { - if (query->radius_id == msg->hdr->identifier) - break; - prev = query; - query = query->next; - } - if (query == NULL) - return RADIUS_RX_UNKNOWN; - - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Found matching Access-Request " - "for RADIUS message (id=%d)\n", query->radius_id); - - 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; - } - - if (msg->hdr->code != RADIUS_CODE_ACCESS_ACCEPT && - msg->hdr->code != RADIUS_CODE_ACCESS_REJECT) { - printf("Unknown RADIUS message code %d to ACL query\n", - msg->hdr->code); - return RADIUS_RX_UNKNOWN; - } - - /* Insert Accept/Reject info into ACL cache */ - cache = wpa_zalloc(sizeof(*cache)); - if (cache == NULL) { - printf("Failed to add ACL cache entry\n"); - goto done; - } - time(&cache->timestamp); - memcpy(cache->addr, query->addr, sizeof(cache->addr)); - if (msg->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) { - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Ignored too " - "small Acct-Interim-Interval %d for " - "STA " MACSTR "\n", - 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_set_radius_acl_auth(hapd, query->addr, cache->accepted, - cache->session_timeout); -#else - /* Re-send original authentication frame for 802.11 processing */ - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Re-sending authentication frame " - "after successful RADIUS ACL query\n"); - ieee802_11_mgmt(hapd, query->auth_msg, query->auth_msg_len, - WLAN_FC_STYPE_AUTH, NULL); -#endif - - done: - if (prev == NULL) - hapd->acl_queries = query->next; - else - prev->next = query->next; - - hostapd_acl_query_free(query); - - return RADIUS_RX_PROCESSED; -} - - -int hostapd_acl_init(struct hostapd_data *hapd) -{ - 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); - - return 0; -} - - -void hostapd_acl_deinit(struct hostapd_data *hapd) -{ - struct hostapd_acl_query_data *query, *prev; - - eloop_cancel_timeout(hostapd_acl_expire, hapd, NULL); - - hostapd_acl_cache_free(hapd->acl_cache); - - query = hapd->acl_queries; - while (query) { - prev = query; - query = query->next; - hostapd_acl_query_free(prev); - } -} - - -int hostapd_acl_reconfig(struct hostapd_data *hapd, - struct hostapd_config *oldconf) -{ - if (!hapd->radius_client_reconfigured) - return 0; - - hostapd_acl_deinit(hapd); - return hostapd_acl_init(hapd); -} - -#endif /* CONFIG_NATIVE_WINDOWS */ diff --git a/contrib/hostapd/ieee802_11_auth.h b/contrib/hostapd/ieee802_11_auth.h deleted file mode 100644 index 0eed825e29a4..000000000000 --- a/contrib/hostapd/ieee802_11_auth.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * hostapd / IEEE 802.11 authentication (ACL) - * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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); -int hostapd_acl_reconfig(struct hostapd_data *hapd, - struct hostapd_config *oldconf); - -#endif /* IEEE802_11_AUTH_H */ diff --git a/contrib/hostapd/ieee802_11h.c b/contrib/hostapd/ieee802_11h.c deleted file mode 100644 index 215e377da552..000000000000 --- a/contrib/hostapd/ieee802_11h.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * hostapd / IEEE 802.11h - * Copyright (c) 2005-2006, Devicescape Software, Inc. - * Copyright (c) 2007, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "hostapd.h" - - -int hostapd_check_power_cap(struct hostapd_data *hapd, u8 *power, u8 len) -{ - unsigned int max_pwr; - - if (len < 2) { - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "Too short power capability IE\n"); - return -1; - } - max_pwr = power[1]; - if (max_pwr > hapd->iface->sta_max_power) - return -1; - return 0; -} diff --git a/contrib/hostapd/ieee802_11h.h b/contrib/hostapd/ieee802_11h.h deleted file mode 100644 index b2bd5497f82f..000000000000 --- a/contrib/hostapd/ieee802_11h.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * hostapd / IEEE 802.11h - * Copyright (c) 2005-2006, Devicescape Software, Inc. - * Copyright (c) 2007, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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_11H_H -#define IEEE802_11H_H - -#define SPECT_LOOSE_BINDING 1 -#define SPECT_STRICT_BINDING 2 - -#define CHAN_SWITCH_MODE_NOISY 0 -#define CHAN_SWITCH_MODE_QUIET 1 - -int hostapd_check_power_cap(struct hostapd_data *hapd, u8 *power, u8 len); - -#endif /* IEEE802_11H_H */ diff --git a/contrib/hostapd/ieee802_1x.c b/contrib/hostapd/ieee802_1x.c deleted file mode 100644 index 53f6b477082a..000000000000 --- a/contrib/hostapd/ieee802_1x.c +++ /dev/null @@ -1,2012 +0,0 @@ -/* - * hostapd / IEEE 802.1X Authenticator - * Copyright (c) 2002-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * $FreeBSD$ - */ - -#include "includes.h" -#include <assert.h> - -#include "hostapd.h" -#include "ieee802_1x.h" -#include "accounting.h" -#include "radius.h" -#include "radius_client.h" -#include "eapol_sm.h" -#include "md5.h" -#include "rc4.h" -#include "eloop.h" -#include "sta_info.h" -#include "wpa.h" -#include "preauth.h" -#include "pmksa_cache.h" -#include "driver.h" -#include "hw_features.h" -#include "eap.h" - - -static void ieee802_1x_new_auth_session(struct hostapd_data *hapd, - struct sta_info *sta); - - -static void ieee802_1x_send(struct hostapd_data *hapd, struct sta_info *sta, - u8 type, u8 *data, size_t datalen) -{ - u8 *buf; - struct ieee802_1x_hdr *xhdr; - size_t len; - int encrypt = 0; - - len = sizeof(*xhdr) + datalen; - buf = wpa_zalloc(len); - if (buf == NULL) { - printf("malloc() failed for ieee802_1x_send(len=%lu)\n", - (unsigned long) len); - return; - } - -#if 0 - /* TODO: - * According to IEEE 802.1aa/D4 EAPOL-Key should be sent before any - * remaining EAP frames, if possible. This would allow rest of the - * frames to be encrypted. This code could be used to request - * encryption from the kernel driver. */ - if (sta->eapol_sm && - sta->eapol_sm->be_auth.state == BE_AUTH_SUCCESS && - sta->eapol_sm->keyTxEnabled) - encrypt = 1; -#endif - - xhdr = (struct ieee802_1x_hdr *) buf; - xhdr->version = hapd->conf->eapol_version; - xhdr->type = type; - xhdr->length = htons(datalen); - - if (datalen > 0 && data != NULL) - 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_send_eapol(hapd, sta->addr, buf, len, encrypt); - } - - 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) { - sta->flags |= WLAN_STA_AUTHORIZED; - res = hostapd_sta_set_flags(hapd, sta->addr, - WLAN_STA_AUTHORIZED, ~0); - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_DEBUG, "authorizing port"); - } else { - sta->flags &= ~WLAN_STA_AUTHORIZED; - res = hostapd_sta_set_flags(hapd, sta->addr, - 0, ~WLAN_STA_AUTHORIZED); - 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_eap_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct sta_info *sta = eloop_ctx; - struct eapol_state_machine *sm = sta->eapol_sm; - if (sm == NULL) - return; - hostapd_logger(sm->hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_DEBUG, "EAP timeout"); - sm->eapTimeout = TRUE; - eapol_sm_step(sm); -} - - -void ieee802_1x_request_identity(struct hostapd_data *hapd, - struct sta_info *sta) -{ - u8 *buf; - struct eap_hdr *eap; - int tlen; - u8 *pos; - struct eapol_state_machine *sm = sta->eapol_sm; - - if (hapd->conf->eap_server) { - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "IEEE 802.1X: Integrated EAP server in " - "use - do not generate EAP-Request/Identity\n"); - return; - } - - if (sm == NULL || !sm->eapRestart) - return; - - ieee802_1x_new_auth_session(hapd, sta); - - tlen = sizeof(*eap) + 1 + hapd->conf->eap_req_id_text_len; - - buf = wpa_zalloc(tlen); - if (buf == NULL) { - printf("Could not allocate memory for identity request\n"); - return; - } - - eap = (struct eap_hdr *) buf; - eap->code = EAP_CODE_REQUEST; - eap->identifier = ++sm->currentId; - eap->length = htons(tlen); - pos = (u8 *) (eap + 1); - *pos++ = EAP_TYPE_IDENTITY; - if (hapd->conf->eap_req_id_text) { - memcpy(pos, hapd->conf->eap_req_id_text, - hapd->conf->eap_req_id_text_len); - } - - sm->eapReq = TRUE; - free(sm->last_eap_radius); - sm->last_eap_radius = buf; - sm->last_eap_radius_len = tlen; - - eloop_cancel_timeout(ieee802_1x_eap_timeout, sta, NULL); - eloop_register_timeout(30, 0, ieee802_1x_eap_timeout, sta, NULL); - sm->eapTimeout = FALSE; - - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "IEEE 802.1X: Generated EAP Request-Identity for " MACSTR - " (identifier %d, timeout 30)\n", MAC2STR(sta->addr), - eap->identifier); - - sm->eapRestart = FALSE; -} - - -void ieee802_1x_tx_canned_eap(struct hostapd_data *hapd, struct sta_info *sta, - int success) -{ - struct eap_hdr eap; - struct eapol_state_machine *sm = sta->eapol_sm; - - memset(&eap, 0, sizeof(eap)); - - eap.code = success ? EAP_CODE_SUCCESS : EAP_CODE_FAILURE; - eap.identifier = 1; - if (sm && sm->last_eap_radius) { - struct eap_hdr *hdr = (struct eap_hdr *) sm->last_eap_radius; - eap.identifier = hdr->identifier + 1; - } - eap.length = htons(sizeof(eap)); - - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "IEEE 802.1X: Sending canned EAP packet %s to " MACSTR - " (identifier %d)\n", success ? "SUCCESS" : "FAILURE", - MAC2STR(sta->addr), eap.identifier); - ieee802_1x_send(hapd, sta, IEEE802_1X_TYPE_EAP_PACKET, (u8 *) &eap, - sizeof(eap)); - if (sm) - sm->dot1xAuthEapolFramesTx++; -} - - -void ieee802_1x_tx_req(struct hostapd_data *hapd, struct sta_info *sta) -{ - struct eap_hdr *eap; - struct eapol_state_machine *sm = sta->eapol_sm; - u8 *type; - if (sm == NULL) - return; - - if (sm->last_eap_radius == NULL) { - printf("Error: TxReq called for station " MACSTR ", but there " - "is no EAP request from the authentication server\n", - MAC2STR(sm->addr)); - return; - } - - eap = (struct eap_hdr *) sm->last_eap_radius; - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "IEEE 802.1X: Sending EAP Packet to " MACSTR - " (identifier %d)\n", MAC2STR(sm->addr), - eap->identifier); - sm->currentId = eap->identifier; - ieee802_1x_send(hapd, sta, IEEE802_1X_TYPE_EAP_PACKET, - sm->last_eap_radius, sm->last_eap_radius_len); - sm->dot1xAuthEapolFramesTx++; - type = (u8 *) (eap + 1); - if (sm->last_eap_radius_len > sizeof(*eap) && - *type == EAP_TYPE_IDENTITY) - sm->dot1xAuthEapolReqIdFramesTx++; - else - sm->dot1xAuthEapolReqFramesTx++; -} - - -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 = wpa_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 (hostapd_get_rand(key->key_iv, sizeof(key->key_iv))) { - printf("Could not get random numbers\n"); - 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 + sm->eapol_key_crypt" as the - * RC4-key */ - memcpy((u8 *) (key + 1), key_data, key_len); - ekey_len = sizeof(key->key_iv) + sm->eapol_key_crypt_len; - ekey = malloc(ekey_len); - if (ekey == NULL) { - printf("Could not encrypt key\n"); - free(buf); - return; - } - memcpy(ekey, key->key_iv, sizeof(key->key_iv)); - memcpy(ekey + sizeof(key->key_iv), sm->eapol_key_crypt, - sm->eapol_key_crypt_len); - rc4((u8 *) (key + 1), key_len, ekey, ekey_len); - 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 = htons(len); - hmac_md5(sm->eapol_key_sign, sm->eapol_key_sign_len, - buf, sizeof(*hdr) + len, - key->key_signature); - - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "IEEE 802.1X: Sending EAPOL-Key to " MACSTR - " (%s index=%d)\n", 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++; - free(buf); -} - - -static struct hostapd_wep_keys * -ieee802_1x_group_alloc(struct hostapd_data *hapd, const char *ifname) -{ - struct hostapd_wep_keys *key; - - key = wpa_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] = malloc(key->default_len); - if (key->key[key->idx] == NULL || - hostapd_get_rand(key->key[key->idx], key->default_len)) { - printf("Could not generate random WEP key (dynamic VLAN).\n"); - free(key->key[key->idx]); - key->key[key->idx] = NULL; - free(key); - return NULL; - } - key->len[key->idx] = key->default_len; - - if (HOSTAPD_DEBUG_COND(HOSTAPD_DEBUG_MINIMAL)) { - printf("%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_set_encryption(ifname, hapd, "WEP", NULL, key->idx, - key->key[key->idx], key->len[key->idx], 1)) - printf("Could not set dynamic VLAN WEP encryption key.\n"); - - hostapd_set_ieee8021x(ifname, hapd, 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]; - - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "IEEE 802.1X: Creating new group " - "state machine for VLAN ID %lu\n", - (unsigned long) vlan_id); - - ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan, vlan_id); - if (ifname == NULL) { - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "IEEE 802.1X: Unknown " - "VLAN ID %lu - cannot create group key state " - "machine\n", (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 = wpa_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 = realloc(ssid->dyn_vlan_keys, size); - if (na == NULL) - return NULL; - ssid->dyn_vlan_keys = na; - 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]; -} - - -void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta) -{ - struct hostapd_wep_keys *key = NULL; - struct eapol_state_machine *sm = sta->eapol_sm; - int vlan_id; - - if (sm == NULL || !sm->eapol_key_sign || !sm->eapol_key_crypt) - return; - - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "IEEE 802.1X: Sending EAPOL-Key(s) to " MACSTR "\n", - MAC2STR(sta->addr)); - - 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 if (hapd->default_wep_key) { - ieee802_1x_tx_key_one(hapd, sta, hapd->default_wep_key_idx, 1, - hapd->default_wep_key, - hapd->conf->default_wep_key_len); - } - - if (hapd->conf->individual_wep_key_len > 0) { - u8 *ikey; - ikey = malloc(hapd->conf->individual_wep_key_len); - if (ikey == NULL || - hostapd_get_rand(ikey, - hapd->conf->individual_wep_key_len)) { - printf("Could not generate random individual WEP " - "key.\n"); - 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_set_encryption(hapd->conf->iface, hapd, "WEP", - sta->addr, 0, ikey, - hapd->conf->individual_wep_key_len, - 1)) { - printf("Could not set individual WEP encryption.\n"); - } - - free(ikey); - } -} - - -const char *radius_mode_txt(struct hostapd_data *hapd) -{ - if (hapd->iface->current_mode == NULL) - return "802.11"; - - switch (hapd->iface->current_mode->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; -} - - -static void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd, - struct sta_info *sta, - u8 *eap, size_t len) -{ - struct radius_msg *msg; - char buf[128]; - struct eapol_state_machine *sm = sta->eapol_sm; - - if (sm == NULL) - return; - - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "Encapsulating EAP message into a RADIUS packet\n"); - - 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, - 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; - } - - 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, strlen(buf))) { - printf("Could not add Called-Station-Id\n"); - goto fail; - } - - 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, 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) { - snprintf(buf, sizeof(buf), "IEEE 802.11i Pre-Authentication"); - } else { - 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, 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 && sm->last_recv_radius->hdr->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) { - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - " Copied RADIUS State Attribute\n"); - } - } - - radius_client_send(hapd->radius, msg, RADIUS_AUTH, sta->addr); - return; - - fail: - radius_msg_free(msg); - free(msg); -} - - -char *eap_type_text(u8 type) -{ - switch (type) { - case EAP_TYPE_IDENTITY: return "Identity"; - case EAP_TYPE_NOTIFICATION: return "Notification"; - case EAP_TYPE_NAK: return "Nak"; - case EAP_TYPE_MD5: return "MD5-Challenge"; - case EAP_TYPE_OTP: return "One-Time Password"; - case EAP_TYPE_GTC: return "Generic Token Card"; - case EAP_TYPE_TLS: return "TLS"; - case EAP_TYPE_TTLS: return "TTLS"; - case EAP_TYPE_PEAP: return "PEAP"; - case EAP_TYPE_SIM: return "SIM"; - case EAP_TYPE_FAST: return "FAST"; - case EAP_TYPE_SAKE: return "SAKE"; - case EAP_TYPE_PSK: return "PSK"; - default: return "Unknown"; - } -} - - -static void handle_eap_response(struct hostapd_data *hapd, - struct sta_info *sta, struct eap_hdr *eap, - u8 *data, size_t len) -{ - u8 type; - struct eapol_state_machine *sm = sta->eapol_sm; - if (sm == NULL) - return; - - if (eap->identifier != sm->currentId) { - hostapd_logger(hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_DEBUG, - "EAP Identifier of the Response-Identity does " - "not match (was %d, expected %d) - ignored", - eap->identifier, sm->currentId); - return; - } - - if (len < 1) { - printf("handle_eap_response: too short response data\n"); - return; - } - - eloop_cancel_timeout(ieee802_1x_eap_timeout, sta, NULL); - - free(sm->last_eap_supp); - sm->last_eap_supp_len = sizeof(*eap) + len; - sm->last_eap_supp = (u8 *) malloc(sm->last_eap_supp_len); - if (sm->last_eap_supp == NULL) { - printf("Could not alloc memory for last EAP Response\n"); - return; - } - memcpy(sm->last_eap_supp, eap, sizeof(*eap)); - memcpy(sm->last_eap_supp + sizeof(*eap), data, len); - - sm->eap_type_supp = type = data[0]; - data++; - len--; - - 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, ntohs(eap->length), - eap_type_text(type), type); - - if (type == EAP_TYPE_IDENTITY) { - char *buf, *pos; - size_t i; - buf = malloc(4 * len + 1); - if (buf) { - pos = buf; - for (i = 0; i < len; i++) { - if (data[i] >= 32 && data[i] < 127) - *pos++ = data[i]; - else { - snprintf(pos, 5, "{%02x}", data[i]); - pos += 4; - } - } - *pos = '\0'; - hostapd_logger(hapd, sm->addr, - HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_DEBUG, - "STA identity '%s'", buf); - free(buf); - } - - sm->rx_identity = TRUE; - sm->dot1xAuthEapolRespIdFramesRx++; - - /* Save station identity for future RADIUS packets */ - free(sm->identity); - sm->identity = malloc(len + 1); - if (sm->identity) { - memcpy(sm->identity, data, len); - sm->identity[len] = '\0'; - sm->identity_len = len; - } - } else - sm->dot1xAuthEapolRespFramesRx++; - - 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 = ntohs(eap->length); - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - " EAP: code=%d identifier=%d length=%d", - eap->code, eap->identifier, eap_len); - if (eap_len < sizeof(*eap)) { - printf(" Invalid EAP length\n"); - return; - } else if (eap_len > len) { - printf(" Too short frame to contain this EAP packet\n"); - return; - } else if (eap_len < len) { - printf(" Ignoring %lu extra bytes after EAP packet\n", - (unsigned long) len - eap_len); - } - - eap_len -= sizeof(*eap); - - switch (eap->code) { - case EAP_CODE_REQUEST: - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, " (request)\n"); - return; - case EAP_CODE_RESPONSE: - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, " (response)\n"); - handle_eap_response(hapd, sta, eap, (u8 *) (eap + 1), eap_len); - break; - case EAP_CODE_SUCCESS: - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, " (success)\n"); - return; - case EAP_CODE_FAILURE: - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, " (failure)\n"); - return; - default: - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, " (unknown code)\n"); - return; - } -} - - -/* Process the EAPOL frames from the Supplicant */ -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; - - if (!hapd->conf->ieee802_1x && !hapd->conf->wpa) - return; - - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "IEEE 802.1X: %lu bytes from " MACSTR "\n", - (unsigned long) len, MAC2STR(sa)); - sta = ap_get_sta(hapd, sa); - if (!sta) { - printf(" no station information available\n"); - return; - } - - if (len < sizeof(*hdr)) { - printf(" too short IEEE 802.1X packet\n"); - return; - } - - hdr = (struct ieee802_1x_hdr *) buf; - datalen = ntohs(hdr->length); - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - " IEEE 802.1X: version=%d type=%d length=%d\n", - 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) { - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - " ignoring %lu extra octets after IEEE 802.1X " - "packet\n", - (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 || - wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_PSK) - return; - - if (!sta->eapol_sm) { - sta->eapol_sm = eapol_sm_alloc(hapd, sta); - if (!sta->eapol_sm) - return; - } - - /* 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"); - 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++; - 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; - sta->eapol_sm->eapolLogoff = TRUE; - sta->eapol_sm->dot1xAuthEapolLogoffFramesRx++; - break; - - case IEEE802_1X_TYPE_EAPOL_KEY: - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, " EAPOL-Key\n"); - if (!(sta->flags & WLAN_STA_AUTHORIZED)) { - printf(" Dropped key data from unauthorized " - "Supplicant\n"); - break; - } - break; - - case IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT: - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - " EAPOL-Encapsulated-ASF-Alert\n"); - /* TODO: implement support for this; show data */ - break; - - default: - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - " unknown IEEE 802.1X packet type\n"); - sta->eapol_sm->dot1xAuthInvalidEapolFramesRx++; - break; - } - - eapol_sm_step(sta->eapol_sm); -} - - -void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta) -{ - struct rsn_pmksa_cache_entry *pmksa; - int reassoc = 1; - - if (!hapd->conf->ieee802_1x || - wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_PSK) - return; - - if (sta->eapol_sm == NULL) { - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_DEBUG, "start authentication"); - sta->eapol_sm = eapol_sm_alloc(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; - } - - sta->eapol_sm->portEnabled = TRUE; - - 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->keyAvailable = 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_sm_step(sta->eapol_sm); - } -} - - -void ieee802_1x_free_radius_class(struct radius_class_data *class) -{ - size_t i; - if (class == NULL) - return; - for (i = 0; i < class->count; i++) - free(class->attr[i].data); - free(class->attr); - class->attr = NULL; - class->count = 0; -} - - -int ieee802_1x_copy_radius_class(struct radius_class_data *dst, - struct radius_class_data *src) -{ - size_t i; - - if (src->attr == NULL) - return 0; - - dst->attr = wpa_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 = malloc(src->attr[i].len); - if (dst->attr[i].data == NULL) - break; - dst->count++; - memcpy(dst->attr[i].data, src->attr[i].data, src->attr[i].len); - dst->attr[i].len = src->attr[i].len; - } - - return 0; -} - - -void ieee802_1x_free_station(struct sta_info *sta) -{ - struct eapol_state_machine *sm = sta->eapol_sm; - - eloop_cancel_timeout(ieee802_1x_eap_timeout, sta, NULL); - - if (sm == NULL) - return; - - sta->eapol_sm = NULL; - - if (sm->last_recv_radius) { - radius_msg_free(sm->last_recv_radius); - free(sm->last_recv_radius); - } - - free(sm->last_eap_supp); - free(sm->last_eap_radius); - free(sm->identity); - ieee802_1x_free_radius_class(&sm->radius_class); - free(sm->eapol_key_sign); - free(sm->eapol_key_crypt); - eapol_sm_free(sm); -} - - -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->eapNoReq = TRUE; - return; - } - - msg = sm->last_recv_radius; - - eap = radius_msg_get_eap(msg, &len); - if (eap == NULL) { - /* draft-aboba-radius-rfc2869bis-20.txt, 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"); - free(sm->last_eap_radius); - sm->last_eap_radius = NULL; - sm->last_eap_radius_len = 0; - sm->eapNoReq = 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"); - free(eap); - sm->eapNoReq = 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; - snprintf(buf, sizeof(buf), "EAP-Request-%s (%d)", - eap_type >= 0 ? eap_type_text(eap_type) : "??", - eap_type); - break; - case EAP_CODE_RESPONSE: - snprintf(buf, sizeof(buf), "EAP Response-%s (%d)", - eap_type >= 0 ? eap_type_text(eap_type) : "??", - eap_type); - break; - case EAP_CODE_SUCCESS: - snprintf(buf, sizeof(buf), "EAP Success"); - break; - case EAP_CODE_FAILURE: - snprintf(buf, sizeof(buf), "EAP Failure"); - break; - default: - snprintf(buf, sizeof(buf), "unknown EAP code"); - 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, ntohs(hdr->length), buf); - sm->eapReq = TRUE; - - free(sm->last_eap_radius); - sm->last_eap_radius = eap; - sm->last_eap_radius_len = len; -} - - -static void ieee802_1x_get_keys(struct hostapd_data *hapd, - struct sta_info *sta, struct radius_msg *msg, - struct radius_msg *req, - 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) { - if (keys->send) { - wpa_hexdump_key(MSG_DEBUG, "MS-MPPE-Send-Key", - keys->send, keys->send_len); - } - if (keys->recv) { - wpa_hexdump_key(MSG_DEBUG, "MS-MPPE-Recv-Key", - keys->recv, keys->recv_len); - } - - if (keys->send && keys->recv) { - free(sm->eapol_key_sign); - free(sm->eapol_key_crypt); - sm->eapol_key_sign = keys->send; - sm->eapol_key_sign_len = keys->send_len; - sm->eapol_key_crypt = keys->recv; - sm->eapol_key_crypt_len = keys->recv_len; - if (hapd->default_wep_key || - hapd->conf->individual_wep_key_len > 0 || - hapd->conf->wpa) - sta->eapol_sm->keyAvailable = TRUE; - } else { - free(keys->send); - free(keys->recv); - } - 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; - - ieee802_1x_free_radius_class(&sm->radius_class); - count = radius_msg_count_attr(msg, RADIUS_ATTR_CLASS, 1); - if (count <= 0) - return; - - nclass = wpa_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 = malloc(class_len); - if (nclass[nclass_count].data == NULL) - break; - - 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; - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "IEEE 802.1X: Stored %lu RADIUS " - "Class attributes for " MACSTR "\n", - (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 = malloc(len + 1); - if (identity == NULL) - return; - - 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); - - 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; -} - - -/* Process the RADIUS frames from Authentication Server */ -static RadiusRxResult -ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req, - 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; - int eap_timeout; - struct eapol_state_machine *sm; - int override_eapReq = 0; - - sm = ieee802_1x_search_radius_identifier(hapd, msg->hdr->identifier); - if (sm == NULL) { - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "IEEE 802.1X: Could not " - "find matching station for this RADIUS " - "message\n"); - 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 (msg->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) { - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Allowing RADIUS " - "Access-Reject without Message-Authenticator " - "since it does not include EAP-Message\n"); - } 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 (msg->hdr->code != RADIUS_CODE_ACCESS_ACCEPT && - msg->hdr->code != RADIUS_CODE_ACCESS_REJECT && - msg->hdr->code != RADIUS_CODE_ACCESS_CHALLENGE) { - printf("Unknown RADIUS message code\n"); - return RADIUS_RX_UNKNOWN; - } - - sm->radius_identifier = -1; - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "RADIUS packet matching with station " MACSTR "\n", - MAC2STR(sta->addr)); - - if (sm->last_recv_radius) { - radius_msg_free(sm->last_recv_radius); - 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->radius->acct_interim_interval == 0 && - msg->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 (msg->hdr->code) { - case RADIUS_CODE_ACCESS_ACCEPT: - if (sta->ssid->dynamic_vlan == DYNAMIC_VLAN_DISABLED) - sta->vlan_id = 0; - 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; - } - - ap_sta_bind_vlan(hapd, sta, old_vlanid); - - /* 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->eapSuccess = 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->keyAvailable && - 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->eapFail = TRUE; - override_eapReq = 1; - break; - case RADIUS_CODE_ACCESS_CHALLENGE: - if (session_timeout_set) { - /* RFC 2869, Ch. 2.3.2; RFC 3580, Ch. 3.17 */ - eap_timeout = session_timeout; - } else - eap_timeout = 30; - hostapd_logger(hapd, sm->addr, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_DEBUG, - "using EAP timeout of %d seconds%s", - eap_timeout, - session_timeout_set ? " (from RADIUS)" : ""); - eloop_cancel_timeout(ieee802_1x_eap_timeout, sta, NULL); - eloop_register_timeout(eap_timeout, 0, ieee802_1x_eap_timeout, - sta, NULL); - sm->eapTimeout = FALSE; - break; - } - - ieee802_1x_decapsulate_radius(hapd, sta); - if (override_eapReq) - sm->eapReq = FALSE; - - eapol_sm_step(sm); - - return RADIUS_RX_QUEUED; -} - - -/* Handler for EAPOL Backend Authentication state machine sendRespToServer. - * Forward the EAP Response from Supplicant to Authentication Server. */ -void ieee802_1x_send_resp_to_server(struct hostapd_data *hapd, - struct sta_info *sta) -{ - struct eapol_state_machine *sm = sta->eapol_sm; - if (sm == NULL) - return; - - if (hapd->conf->eap_server) { - eap_set_eapRespData(sm->eap, sm->last_eap_supp, - sm->last_eap_supp_len); - } else { - ieee802_1x_encapsulate_radius(hapd, sta, sm->last_eap_supp, - sm->last_eap_supp_len); - } -} - - -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"); - - if (sm->last_recv_radius) { - radius_msg_free(sm->last_recv_radius); - free(sm->last_recv_radius); - sm->last_recv_radius = NULL; - } - free(sm->last_eap_supp); - sm->last_eap_supp = NULL; - sm->last_eap_supp_len = 0; - free(sm->last_eap_radius); - sm->last_eap_radius = NULL; - sm->last_eap_radius_len = 0; -} - - -#ifdef HOSTAPD_DUMP_STATE -static void fprint_char(FILE *f, char c) -{ - if (c >= 32 && c < 127) - fprintf(f, "%c", c); - else - fprintf(f, "<%02x>", c); -} - - -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_type_text(sm->eap_type_authsrv), - sm->eap_type_supp, eap_type_text(sm->eap_type_supp)); - - fprintf(f, "%scached_packets=%s%s%s\n", prefix, - sm->last_recv_radius ? "[RX RADIUS]" : "", - sm->last_eap_radius ? "[EAP RADIUS]" : "", - sm->last_eap_supp ? "[EAP SUPPLICANT]" : ""); - - eapol_sm_dump_state(f, prefix, sm); -} -#endif /* HOSTAPD_DUMP_STATE */ - - -static int ieee802_1x_rekey_broadcast(struct hostapd_data *hapd) -{ - if (hapd->conf->default_wep_key_len < 1) - return 0; - - free(hapd->default_wep_key); - hapd->default_wep_key = malloc(hapd->conf->default_wep_key_len); - if (hapd->default_wep_key == NULL || - hostapd_get_rand(hapd->default_wep_key, - hapd->conf->default_wep_key_len)) { - printf("Could not generate random WEP key.\n"); - free(hapd->default_wep_key); - hapd->default_wep_key = NULL; - return -1; - } - - wpa_hexdump_key(MSG_DEBUG, "IEEE 802.1X: New default WEP key", - hapd->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->keyAvailable = TRUE; - eapol_sm_step(sta->eapol_sm); - } - return 0; -} - - -static void ieee802_1x_rekey(void *eloop_ctx, void *timeout_ctx) -{ - struct hostapd_data *hapd = eloop_ctx; - - if (hapd->default_wep_key_idx >= 3) - hapd->default_wep_key_idx = - hapd->conf->individual_wep_key_len > 0 ? 1 : 0; - else - hapd->default_wep_key_idx++; - - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "IEEE 802.1X: New default WEP " - "key index %d\n", hapd->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"); - free(hapd->default_wep_key); - hapd->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_set_encryption(hapd->conf->iface, hapd, "WEP", NULL, - hapd->default_wep_key_idx, - hapd->default_wep_key, - hapd->conf->default_wep_key_len, 1)) { - hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE8021X, - HOSTAPD_LEVEL_WARNING, "failed to configure a " - "new broadcast key"); - free(hapd->default_wep_key); - hapd->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); - } -} - - -int ieee802_1x_init(struct hostapd_data *hapd) -{ - int i; - - if ((hapd->conf->ieee802_1x || hapd->conf->wpa) && - hostapd_set_ieee8021x(hapd->conf->iface, hapd, 1)) - return -1; - - if (radius_client_register(hapd->radius, RADIUS_AUTH, - ieee802_1x_receive_auth, hapd)) - return -1; - - if (hapd->conf->default_wep_key_len) { - hostapd_set_privacy(hapd, 1); - - for (i = 0; i < 4; i++) - hostapd_set_encryption(hapd->conf->iface, hapd, - "none", NULL, i, NULL, 0, 0); - - ieee802_1x_rekey(hapd, NULL); - - if (hapd->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_ieee8021x(hapd->conf->iface, hapd, 0); -} - - -int ieee802_1x_reconfig(struct hostapd_data *hapd, - struct hostapd_config *oldconf, - struct hostapd_bss_config *oldbss) -{ - ieee802_1x_deinit(hapd); - return ieee802_1x_init(hapd); -} - - -static void ieee802_1x_new_auth_session(struct hostapd_data *hapd, - struct sta_info *sta) -{ - struct eapol_state_machine *sm = sta->eapol_sm; - if (sm == NULL) - return; - - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "IEEE 802.1X: station " MACSTR " - new auth session, " - "clearing State\n", MAC2STR(sta->addr)); - - if (sm->last_recv_radius) { - radius_msg_free(sm->last_recv_radius); - free(sm->last_recv_radius); - sm->last_recv_radius = NULL; - } - - sm->eapSuccess = FALSE; - sm->eapFail = FALSE; -} - - -int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta, - u8 *buf, size_t len, int ack) -{ - struct ieee80211_hdr *hdr; - struct ieee802_1x_hdr *xhdr; - struct ieee802_1x_eapol_key *key; - u8 *pos; - - if (sta == NULL) - return -1; - if (len < sizeof(*hdr) + sizeof(rfc1042_header) + 2 + sizeof(*xhdr)) - return 0; - - hdr = (struct ieee80211_hdr *) buf; - pos = (u8 *) (hdr + 1); - if (memcmp(pos, rfc1042_header, sizeof(rfc1042_header)) != 0) - return 0; - pos += sizeof(rfc1042_header); - if (((pos[0] << 8) | pos[1]) != ETH_P_PAE) - return 0; - pos += 2; - - xhdr = (struct ieee802_1x_hdr *) pos; - pos += sizeof(*xhdr); - - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "IEEE 802.1X: " MACSTR - " TX status - version=%d type=%d length=%d - ack=%d\n", - MAC2STR(sta->addr), xhdr->version, xhdr->type, - ntohs(xhdr->length), 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; -} - - -u8 * ieee802_1x_get_key_crypt(struct eapol_state_machine *sm, size_t *len) -{ - if (sm == NULL) - return NULL; - - *len = sm->eapol_key_crypt_len; - return sm->eapol_key_crypt; -} - - -void ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm, - int enabled) -{ - if (sm == NULL) - return; - sm->portEnabled = enabled ? TRUE : FALSE; - eapol_sm_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_sm_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 = 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 = 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 = 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 = 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 = 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_auth_sta_key_mgmt(sta->wpa_sm) == - WPA_KEY_MGMT_IEEE8021X ? 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; -} - - -void ieee802_1x_finished(struct hostapd_data *hapd, struct sta_info *sta, - int success) -{ - u8 *key; - size_t len; - /* TODO: get PMKLifetime from WPA parameters */ - static const int dot11RSNAConfigPMKLifetime = 43200; - - key = ieee802_1x_get_key_crypt(sta->eapol_sm, &len); - if (success && key && - 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)"); - } -} diff --git a/contrib/hostapd/ieee802_1x.h b/contrib/hostapd/ieee802_1x.h deleted file mode 100644 index 776d9df8089f..000000000000 --- a/contrib/hostapd/ieee802_1x.h +++ /dev/null @@ -1,92 +0,0 @@ -/* $FreeBSD$ */ - -/* - * hostapd / IEEE 802.1X Authenticator - * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 - -/* draft-congdon-radius-8021x-20.txt */ - -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 */ -} __attribute__ ((packed)); - - -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_request_identity(struct hostapd_data *hapd, - struct sta_info *sta); -void ieee802_1x_tx_canned_eap(struct hostapd_data *hapd, struct sta_info *sta, - int success); -void ieee802_1x_tx_req(struct hostapd_data *hapd, struct sta_info *sta); -void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta); -void ieee802_1x_send_resp_to_server(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_reconfig(struct hostapd_data *hapd, - struct hostapd_config *oldconf, - struct hostapd_bss_config *oldbss); -int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta, - 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); -u8 * ieee802_1x_get_key_crypt(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); -void ieee802_1x_finished(struct hostapd_data *hapd, struct sta_info *sta, - int success); -char *eap_type_text(u8 type); - -struct radius_class_data; - -void ieee802_1x_free_radius_class(struct radius_class_data *class); -int ieee802_1x_copy_radius_class(struct radius_class_data *dst, - struct radius_class_data *src); - -#endif /* IEEE802_1X_H */ diff --git a/contrib/hostapd/includes.h b/contrib/hostapd/includes.h deleted file mode 100644 index 84308c3a37a2..000000000000 --- a/contrib/hostapd/includes.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * wpa_supplicant/hostapd - Default include files - * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 #ifdefs 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 <stdlib.h> -#include <stdio.h> -#include <stdarg.h> -#include <string.h> -#ifndef _WIN32_WCE -#ifndef CONFIG_TI_COMPILER -#include <signal.h> -#include <sys/types.h> -#endif /* CONFIG_TI_COMPILER */ -#include <errno.h> -#endif /* _WIN32_WCE */ -#include <ctype.h> -#include <time.h> - -#ifndef CONFIG_TI_COMPILER -#ifndef _MSC_VER -#include <unistd.h> -#endif /* _MSC_VER */ -#endif /* CONFIG_TI_COMPILER */ - -#ifndef CONFIG_NATIVE_WINDOWS -#ifndef CONFIG_TI_COMPILER -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#ifndef __vxworks -#include <sys/uio.h> -#include <sys/time.h> -#endif /* __vxworks */ -#endif /* CONFIG_TI_COMPILER */ -#endif /* CONFIG_NATIVE_WINDOWS */ - -#endif /* INCLUDES_H */ diff --git a/contrib/hostapd/l2_packet.h b/contrib/hostapd/l2_packet.h deleted file mode 100644 index 540f0a116b56..000000000000 --- a/contrib/hostapd/l2_packet.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * WPA Supplicant - Layer2 packet interface definition - * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 - -#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] -#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" - -#ifndef ETH_P_EAPOL -#define ETH_P_EAPOL 0x888e -#endif - -#ifndef ETH_P_RSN_PREAUTH -#define ETH_P_RSN_PREAUTH 0x88c7 -#endif - -/** - * 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]; - u16 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/contrib/hostapd/l2_packet_none.c b/contrib/hostapd/l2_packet_none.c deleted file mode 100644 index 2add5b7caa43..000000000000 --- a/contrib/hostapd/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 <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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_strncpy(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/contrib/hostapd/logwatch/README b/contrib/hostapd/logwatch/README deleted file mode 100644 index 3cba51190963..000000000000 --- a/contrib/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/contrib/hostapd/logwatch/hostapd b/contrib/hostapd/logwatch/hostapd deleted file mode 100755 index 97b24ef6e1b8..000000000000 --- a/contrib/hostapd/logwatch/hostapd +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/perl -w -# -# Logwatch script for hostapd -# -# Copyright 2005 Henrik Brix Andersen <brix@gentoo.org> -# 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 = <STDIN>)) { - 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/contrib/hostapd/logwatch/hostapd.conf b/contrib/hostapd/logwatch/hostapd.conf deleted file mode 100644 index 5bebe6ad2c1b..000000000000 --- a/contrib/hostapd/logwatch/hostapd.conf +++ /dev/null @@ -1,10 +0,0 @@ -# Logwatch configuration for hostapd -# -# Copyright 2005 Henrik Brix Andersen <brix@gentoo.org> -# 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/contrib/hostapd/madwifi.conf b/contrib/hostapd/madwifi.conf deleted file mode 100644 index ed3704fcb634..000000000000 --- a/contrib/hostapd/madwifi.conf +++ /dev/null @@ -1,278 +0,0 @@ -##### hostapd configuration file ############################################## -# Empty lines and lines starting with # are ignored - -# AP netdevice name (without 'ap' prefix, i.e., wlan0 uses wlan0ap for -# management frames) -interface=ath0 - -# In case of madwifi driver, an additional configuration parameter, bridge, -# must be used to notify hostapd if the interface is included in a bridge. This -# parameter is not used with Host AP driver. -bridge=br0 - -# Driver interface type (hostap/wired/madwifi; default: hostap) -driver=madwifi - -# 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 -# -# 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 - -# Debugging: 0 = no, 1 = minimal, 2 = verbose, 3 = msg dumps, 4 = excessive -debug=0 - -# Dump file for state information (on SIGUSR1) -dump_file=/tmp/hostapd.dump - - -##### IEEE 802.11 related configuration ####################################### - -# SSID to be used in IEEE 802.11 management frames -ssid=wpa-test - -##### IEEE 802.1X-REV related configuration ################################### - -# Require IEEE 802.1X authorization -#ieee8021x=1 - -# 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 - - -##### 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 - -# 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 file name for the GSM -# authentication triplets. -#eap_sim_db=/etc/hostapd.sim_db - - -##### 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. -#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 - - -##### RADIUS authentication server configuration ############################## - -# hostapd can be used as a RADIUS authentication server for other hosts. This -# requires that the integrated EAP authenticator 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. -# (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) -#wpa_pairwise=TKIP 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 - -# 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 diff --git a/contrib/hostapd/md4.c b/contrib/hostapd/md4.c deleted file mode 100644 index 41c84a3a7b5d..000000000000 --- a/contrib/hostapd/md4.c +++ /dev/null @@ -1,282 +0,0 @@ -/* - * MD4 hash implementation - * Copyright (c) 2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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" - - -#ifdef INTERNAL_MD4 - -#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); - - -void 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); -} - - -/* ===== 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<<s | 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 ===== */ - -#endif /* INTERNAL_MD4 */ diff --git a/contrib/hostapd/md5.c b/contrib/hostapd/md5.c deleted file mode 100644 index a7db7aa9a771..000000000000 --- a/contrib/hostapd/md5.c +++ /dev/null @@ -1,394 +0,0 @@ -/* - * MD5 hash implementation and interface functions - * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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) - */ -void 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; - } - - /* if key is longer than 64 bytes reset it to key = MD5(key) */ - if (key_len > 64) { - md5_vector(1, &key, &key_len, tk); - 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]; - } - md5_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 MD5 */ - _addr[0] = k_pad; - _len[0] = 64; - _addr[1] = mac; - _len[1] = MD5_MAC_LEN; - 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) - */ -void hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len, - u8 *mac) -{ - hmac_md5_vector(key, key_len, 1, &data, &data_len, mac); -} - - -#ifdef INTERNAL_MD5 - -struct MD5Context { - u32 buf[4]; - u32 bits[2]; - u8 in[64]; -}; - -#ifndef CONFIG_CRYPTO_INTERNAL -static void MD5Init(struct MD5Context *context); -static void MD5Update(struct MD5Context *context, unsigned char const *buf, - unsigned len); -static void MD5Final(unsigned char digest[16], struct MD5Context *context); -#endif /* CONFIG_CRYPTO_INTERNAL */ -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 - */ -void 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); -} - - -/* ===== 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(ctx)); /* 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<<s | 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 ===== */ - -#endif /* INTERNAL_MD5 */ diff --git a/contrib/hostapd/md5.h b/contrib/hostapd/md5.h deleted file mode 100644 index e82f3969ed08..000000000000 --- a/contrib/hostapd/md5.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * MD5 hash implementation and interface functions - * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 - -void hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac); -void hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len, - u8 *mac); - -#ifdef CONFIG_CRYPTO_INTERNAL -struct MD5Context; - -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 /* CONFIG_CRYPTO_INTERNAL */ - -#endif /* MD5_H */ diff --git a/contrib/hostapd/milenage.c b/contrib/hostapd/milenage.c deleted file mode 100644 index ab8bbd5e4f91..000000000000 --- a/contrib/hostapd/milenage.c +++ /dev/null @@ -1,1053 +0,0 @@ -/* - * 3GPP AKA - Milenage algorithm (3GPP TS 35.205, .206, .207, .208) - * Copyright (c) 2006 <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "milenage.h" -#include "aes_wrap.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 - */ -static void 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]; - aes_128_encrypt_block(k, tmp1, tmp1); - - /* tmp2 = IN1 = SQN || AMF || SQN || AMF */ - memcpy(tmp2, sqn, 6); - memcpy(tmp2 + 6, amf, 2); - 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 */ - aes_128_encrypt_block(k, tmp3, tmp1); - for (i = 0; i < 16; i++) - tmp1[i] ^= opc[i]; - if (mac_a) - memcpy(mac_a, tmp1, 8); /* f1 */ - if (mac_s) - memcpy(mac_s, tmp1 + 8, 8); /* f1* */ -} - - -/** - * 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 - */ -static void 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]; - aes_128_encrypt_block(k, tmp1, tmp2); - - /* 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 */ - aes_128_encrypt_block(k, tmp1, tmp3); - for (i = 0; i < 16; i++) - tmp3[i] ^= opc[i]; - if (res) - memcpy(res, tmp3 + 8, 8); /* f2 */ - if (ak) - 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) */ - aes_128_encrypt_block(k, tmp1, ck); - 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) */ - aes_128_encrypt_block(k, tmp1, ik); - 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) */ - aes_128_encrypt_block(k, tmp1, tmp1); - for (i = 0; i < 6; i++) - akstar[i] = tmp1[i] ^ opc[i]; - } -} - - -/** - * 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[16], ak[6]; - - if (*res_len < 8) { - *res_len = 0; - return; - } - *res_len = 8; - milenage_f1(opc, k, _rand, sqn, amf, mac_a, NULL); - milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL); - - /* AUTN = (SQN ^ AK) || AMF || MAC */ - for (i = 0; i < 6; i++) - autn[i] = sqn[i] ^ ak[i]; - memcpy(autn + 6, amf, 2); - 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; - - milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak); - for (i = 0; i < 6; i++) - sqn[i] = auts[i] ^ ak[i]; - milenage_f1(opc, k, _rand, sqn, amf, NULL, mac_s); - if (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 - */ -void gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres, - u8 *kc) -{ - u8 res[8], ck[16], ik[16]; - int i; - - milenage_f2345(opc, k, _rand, res, ck, ik, NULL, NULL); - - for (i = 0; i < 8; i++) - kc[i] = ck[i] ^ ck[i + 8] ^ ik[i] ^ ik[i + 8]; - -#ifdef GSM_MILENAGE_ALT_SRES - 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 */ -} - - -#ifdef TEST_MAIN_MILENAGE - -extern int wpa_debug_level; - - -/** - * milenage_opc - Determine OPc from OP and K - * @op: OP = 128-bit operator variant algorithm configuration field - * @k: K = 128-bit subscriber key - * @opc: Buffer for OPc = 128-bit value derived from OP and K - */ -static void milenage_opc(const u8 *op, const u8 *k, u8 *opc) -{ - int i; - /* OP_C = OP XOR E_K(OP) */ - aes_128_encrypt_block(k, op, opc); - for (i = 0; i < 16; i++) - opc[i] ^= op[i]; -} - - -struct gsm_milenage_test_set { - u8 ki[16]; - u8 rand[16]; - u8 opc[16]; - u8 sres1[4]; - u8 sres2[4]; - u8 kc[8]; -}; - -static const struct gsm_milenage_test_set gsm_test_sets[] = -{ - { - /* 3GPP TS 55.205 v6.0.0 - Test Set 1 */ - { 0x46, 0x5b, 0x5c, 0xe8, 0xb1, 0x99, 0xb4, 0x9f, - 0xaa, 0x5f, 0x0a, 0x2e, 0xe2, 0x38, 0xa6, 0xbc }, - { 0x23, 0x55, 0x3c, 0xbe, 0x96, 0x37, 0xa8, 0x9d, - 0x21, 0x8a, 0xe6, 0x4d, 0xae, 0x47, 0xbf, 0x35 }, - { 0xcd, 0x63, 0xcb, 0x71, 0x95, 0x4a, 0x9f, 0x4e, - 0x48, 0xa5, 0x99, 0x4e, 0x37, 0xa0, 0x2b, 0xaf }, - { 0x46, 0xf8, 0x41, 0x6a }, - { 0xa5, 0x42, 0x11, 0xd5 }, - { 0xea, 0xe4, 0xbe, 0x82, 0x3a, 0xf9, 0xa0, 0x8b } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 2 */ - { 0xfe, 0xc8, 0x6b, 0xa6, 0xeb, 0x70, 0x7e, 0xd0, - 0x89, 0x05, 0x75, 0x7b, 0x1b, 0xb4, 0x4b, 0x8f }, - { 0x9f, 0x7c, 0x8d, 0x02, 0x1a, 0xcc, 0xf4, 0xdb, - 0x21, 0x3c, 0xcf, 0xf0, 0xc7, 0xf7, 0x1a, 0x6a }, - { 0x10, 0x06, 0x02, 0x0f, 0x0a, 0x47, 0x8b, 0xf6, - 0xb6, 0x99, 0xf1, 0x5c, 0x06, 0x2e, 0x42, 0xb3 }, - { 0x8c, 0x30, 0x8a, 0x5e }, - { 0x80, 0x11, 0xc4, 0x8c }, - { 0xaa, 0x01, 0x73, 0x9b, 0x8c, 0xaa, 0x97, 0x6d } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 3 */ - { 0x9e, 0x59, 0x44, 0xae, 0xa9, 0x4b, 0x81, 0x16, - 0x5c, 0x82, 0xfb, 0xf9, 0xf3, 0x2d, 0xb7, 0x51 }, - { 0xce, 0x83, 0xdb, 0xc5, 0x4a, 0xc0, 0x27, 0x4a, - 0x15, 0x7c, 0x17, 0xf8, 0x0d, 0x01, 0x7b, 0xd6 }, - { 0xa6, 0x4a, 0x50, 0x7a, 0xe1, 0xa2, 0xa9, 0x8b, - 0xb8, 0x8e, 0xb4, 0x21, 0x01, 0x35, 0xdc, 0x87 }, - { 0xcf, 0xbc, 0xe3, 0xfe }, - { 0xf3, 0x65, 0xcd, 0x68 }, - { 0x9a, 0x8e, 0xc9, 0x5f, 0x40, 0x8c, 0xc5, 0x07 } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 4 */ - { 0x4a, 0xb1, 0xde, 0xb0, 0x5c, 0xa6, 0xce, 0xb0, - 0x51, 0xfc, 0x98, 0xe7, 0x7d, 0x02, 0x6a, 0x84 }, - { 0x74, 0xb0, 0xcd, 0x60, 0x31, 0xa1, 0xc8, 0x33, - 0x9b, 0x2b, 0x6c, 0xe2, 0xb8, 0xc4, 0xa1, 0x86 }, - { 0xdc, 0xf0, 0x7c, 0xbd, 0x51, 0x85, 0x52, 0x90, - 0xb9, 0x2a, 0x07, 0xa9, 0x89, 0x1e, 0x52, 0x3e }, - { 0x96, 0x55, 0xe2, 0x65 }, - { 0x58, 0x60, 0xfc, 0x1b }, - { 0xcd, 0xc1, 0xdc, 0x08, 0x41, 0xb8, 0x1a, 0x22 } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 5 */ - { 0x6c, 0x38, 0xa1, 0x16, 0xac, 0x28, 0x0c, 0x45, - 0x4f, 0x59, 0x33, 0x2e, 0xe3, 0x5c, 0x8c, 0x4f }, - { 0xee, 0x64, 0x66, 0xbc, 0x96, 0x20, 0x2c, 0x5a, - 0x55, 0x7a, 0xbb, 0xef, 0xf8, 0xba, 0xbf, 0x63 }, - { 0x38, 0x03, 0xef, 0x53, 0x63, 0xb9, 0x47, 0xc6, - 0xaa, 0xa2, 0x25, 0xe5, 0x8f, 0xae, 0x39, 0x34 }, - { 0x13, 0x68, 0x8f, 0x17 }, - { 0x16, 0xc8, 0x23, 0x3f }, - { 0xdf, 0x75, 0xbc, 0x5e, 0xa8, 0x99, 0x87, 0x9f } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 6 */ - { 0x2d, 0x60, 0x9d, 0x4d, 0xb0, 0xac, 0x5b, 0xf0, - 0xd2, 0xc0, 0xde, 0x26, 0x70, 0x14, 0xde, 0x0d }, - { 0x19, 0x4a, 0xa7, 0x56, 0x01, 0x38, 0x96, 0xb7, - 0x4b, 0x4a, 0x2a, 0x3b, 0x0a, 0xf4, 0x53, 0x9e }, - { 0xc3, 0x5a, 0x0a, 0xb0, 0xbc, 0xbf, 0xc9, 0x25, - 0x2c, 0xaf, 0xf1, 0x5f, 0x24, 0xef, 0xbd, 0xe0 }, - { 0x55, 0x3d, 0x00, 0xb3 }, - { 0x8c, 0x25, 0xa1, 0x6c }, - { 0x84, 0xb4, 0x17, 0xae, 0x3a, 0xea, 0xb4, 0xf3 } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 7 */ - { 0xa5, 0x30, 0xa7, 0xfe, 0x42, 0x8f, 0xad, 0x10, - 0x82, 0xc4, 0x5e, 0xdd, 0xfc, 0xe1, 0x38, 0x84 }, - { 0x3a, 0x4c, 0x2b, 0x32, 0x45, 0xc5, 0x0e, 0xb5, - 0xc7, 0x1d, 0x08, 0x63, 0x93, 0x95, 0x76, 0x4d }, - { 0x27, 0x95, 0x3e, 0x49, 0xbc, 0x8a, 0xf6, 0xdc, - 0xc6, 0xe7, 0x30, 0xeb, 0x80, 0x28, 0x6b, 0xe3 }, - { 0x59, 0xf1, 0xa4, 0x4a }, - { 0xa6, 0x32, 0x41, 0xe1 }, - { 0x3b, 0x4e, 0x24, 0x4c, 0xdc, 0x60, 0xce, 0x03 } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 8 */ - { 0xd9, 0x15, 0x1c, 0xf0, 0x48, 0x96, 0xe2, 0x58, - 0x30, 0xbf, 0x2e, 0x08, 0x26, 0x7b, 0x83, 0x60 }, - { 0xf7, 0x61, 0xe5, 0xe9, 0x3d, 0x60, 0x3f, 0xeb, - 0x73, 0x0e, 0x27, 0x55, 0x6c, 0xb8, 0xa2, 0xca }, - { 0xc4, 0xc9, 0x3e, 0xff, 0xe8, 0xa0, 0x81, 0x38, - 0xc2, 0x03, 0xd4, 0xc2, 0x7c, 0xe4, 0xe3, 0xd9 }, - { 0x50, 0x58, 0x88, 0x61 }, - { 0x4a, 0x90, 0xb2, 0x17 }, - { 0x8d, 0x4e, 0xc0, 0x1d, 0xe5, 0x97, 0xac, 0xfe } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 9 */ - { 0xa0, 0xe2, 0x97, 0x1b, 0x68, 0x22, 0xe8, 0xd3, - 0x54, 0xa1, 0x8c, 0xc2, 0x35, 0x62, 0x4e, 0xcb }, - { 0x08, 0xef, 0xf8, 0x28, 0xb1, 0x3f, 0xdb, 0x56, - 0x27, 0x22, 0xc6, 0x5c, 0x7f, 0x30, 0xa9, 0xb2 }, - { 0x82, 0xa2, 0x6f, 0x22, 0xbb, 0xa9, 0xe9, 0x48, - 0x8f, 0x94, 0x9a, 0x10, 0xd9, 0x8e, 0x9c, 0xc4 }, - { 0xcd, 0xe6, 0xb0, 0x27 }, - { 0x4b, 0xc2, 0x21, 0x2d }, - { 0xd8, 0xde, 0xbc, 0x4f, 0xfb, 0xcd, 0x60, 0xaa } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 10 */ - { 0x0d, 0xa6, 0xf7, 0xba, 0x86, 0xd5, 0xea, 0xc8, - 0xa1, 0x9c, 0xf5, 0x63, 0xac, 0x58, 0x64, 0x2d }, - { 0x67, 0x9a, 0xc4, 0xdb, 0xac, 0xd7, 0xd2, 0x33, - 0xff, 0x9d, 0x68, 0x06, 0xf4, 0x14, 0x9c, 0xe3 }, - { 0x0d, 0xb1, 0x07, 0x1f, 0x87, 0x67, 0x56, 0x2c, - 0xa4, 0x3a, 0x0a, 0x64, 0xc4, 0x1e, 0x8d, 0x08 }, - { 0x02, 0xd1, 0x3a, 0xcd }, - { 0x6f, 0xc3, 0x0f, 0xee }, - { 0xf0, 0xea, 0xa5, 0x0a, 0x1e, 0xdc, 0xeb, 0xb7 } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 11 */ - { 0x77, 0xb4, 0x58, 0x43, 0xc8, 0x8e, 0x58, 0xc1, - 0x0d, 0x20, 0x26, 0x84, 0x51, 0x5e, 0xd4, 0x30 }, - { 0x4c, 0x47, 0xeb, 0x30, 0x76, 0xdc, 0x55, 0xfe, - 0x51, 0x06, 0xcb, 0x20, 0x34, 0xb8, 0xcd, 0x78 }, - { 0xd4, 0x83, 0xaf, 0xae, 0x56, 0x24, 0x09, 0xa3, - 0x26, 0xb5, 0xbb, 0x0b, 0x20, 0xc4, 0xd7, 0x62 }, - { 0x44, 0x38, 0x9d, 0x01 }, - { 0xae, 0xfa, 0x35, 0x7b }, - { 0x82, 0xdb, 0xab, 0x7f, 0x83, 0xf0, 0x63, 0xda } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 12 */ - { 0x72, 0x9b, 0x17, 0x72, 0x92, 0x70, 0xdd, 0x87, - 0xcc, 0xdf, 0x1b, 0xfe, 0x29, 0xb4, 0xe9, 0xbb }, - { 0x31, 0x1c, 0x4c, 0x92, 0x97, 0x44, 0xd6, 0x75, - 0xb7, 0x20, 0xf3, 0xb7, 0xe9, 0xb1, 0xcb, 0xd0 }, - { 0x22, 0x8c, 0x2f, 0x2f, 0x06, 0xac, 0x32, 0x68, - 0xa9, 0xe6, 0x16, 0xee, 0x16, 0xdb, 0x4b, 0xa1 }, - { 0x03, 0xe0, 0xfd, 0x84 }, - { 0x98, 0xdb, 0xbd, 0x09 }, - { 0x3c, 0x66, 0xcb, 0x98, 0xca, 0xb2, 0xd3, 0x3d } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 13 */ - { 0xd3, 0x2d, 0xd2, 0x3e, 0x89, 0xdc, 0x66, 0x23, - 0x54, 0xca, 0x12, 0xeb, 0x79, 0xdd, 0x32, 0xfa }, - { 0xcf, 0x7d, 0x0a, 0xb1, 0xd9, 0x43, 0x06, 0x95, - 0x0b, 0xf1, 0x20, 0x18, 0xfb, 0xd4, 0x68, 0x87 }, - { 0xd2, 0x2a, 0x4b, 0x41, 0x80, 0xa5, 0x32, 0x57, - 0x08, 0xa5, 0xff, 0x70, 0xd9, 0xf6, 0x7e, 0xc7 }, - { 0xbe, 0x73, 0xb3, 0xdc }, - { 0xaf, 0x4a, 0x41, 0x1e }, - { 0x96, 0x12, 0xb5, 0xd8, 0x8a, 0x41, 0x30, 0xbb } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 14 */ - { 0xaf, 0x7c, 0x65, 0xe1, 0x92, 0x72, 0x21, 0xde, - 0x59, 0x11, 0x87, 0xa2, 0xc5, 0x98, 0x7a, 0x53 }, - { 0x1f, 0x0f, 0x85, 0x78, 0x46, 0x4f, 0xd5, 0x9b, - 0x64, 0xbe, 0xd2, 0xd0, 0x94, 0x36, 0xb5, 0x7a }, - { 0xa4, 0xcf, 0x5c, 0x81, 0x55, 0xc0, 0x8a, 0x7e, - 0xff, 0x41, 0x8e, 0x54, 0x43, 0xb9, 0x8e, 0x55 }, - { 0x8f, 0xe0, 0x19, 0xc7 }, - { 0x7b, 0xff, 0xa5, 0xc2 }, - { 0x75, 0xa1, 0x50, 0xdf, 0x3c, 0x6a, 0xed, 0x08 } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 15 */ - { 0x5b, 0xd7, 0xec, 0xd3, 0xd3, 0x12, 0x7a, 0x41, - 0xd1, 0x25, 0x39, 0xbe, 0xd4, 0xe7, 0xcf, 0x71 }, - { 0x59, 0xb7, 0x5f, 0x14, 0x25, 0x1c, 0x75, 0x03, - 0x1d, 0x0b, 0xcb, 0xac, 0x1c, 0x2c, 0x04, 0xc7 }, - { 0x76, 0x08, 0x9d, 0x3c, 0x0f, 0xf3, 0xef, 0xdc, - 0x6e, 0x36, 0x72, 0x1d, 0x4f, 0xce, 0xb7, 0x47 }, - { 0x27, 0x20, 0x2b, 0x82 }, - { 0x7e, 0x3f, 0x44, 0xc7 }, - { 0xb7, 0xf9, 0x2e, 0x42, 0x6a, 0x36, 0xfe, 0xc5 } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 16 */ - { 0x6c, 0xd1, 0xc6, 0xce, 0xb1, 0xe0, 0x1e, 0x14, - 0xf1, 0xb8, 0x23, 0x16, 0xa9, 0x0b, 0x7f, 0x3d }, - { 0xf6, 0x9b, 0x78, 0xf3, 0x00, 0xa0, 0x56, 0x8b, - 0xce, 0x9f, 0x0c, 0xb9, 0x3c, 0x4b, 0xe4, 0xc9 }, - { 0xa2, 0x19, 0xdc, 0x37, 0xf1, 0xdc, 0x7d, 0x66, - 0x73, 0x8b, 0x58, 0x43, 0xc7, 0x99, 0xf2, 0x06 }, - { 0xdd, 0xd7, 0xef, 0xe6 }, - { 0x70, 0xf6, 0xbd, 0xb9 }, - { 0x88, 0xd9, 0xde, 0x10, 0xa2, 0x20, 0x04, 0xc5 } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 17 */ - { 0xb7, 0x3a, 0x90, 0xcb, 0xcf, 0x3a, 0xfb, 0x62, - 0x2d, 0xba, 0x83, 0xc5, 0x8a, 0x84, 0x15, 0xdf }, - { 0xb1, 0x20, 0xf1, 0xc1, 0xa0, 0x10, 0x2a, 0x2f, - 0x50, 0x7d, 0xd5, 0x43, 0xde, 0x68, 0x28, 0x1f }, - { 0xdf, 0x0c, 0x67, 0x86, 0x8f, 0xa2, 0x5f, 0x74, - 0x8b, 0x70, 0x44, 0xc6, 0xe7, 0xc2, 0x45, 0xb8 }, - { 0x67, 0xe4, 0xff, 0x3f }, - { 0x47, 0x9d, 0xd2, 0x5c }, - { 0xa8, 0x19, 0xe5, 0x77, 0xa8, 0xd6, 0x17, 0x5b } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 18 */ - { 0x51, 0x22, 0x25, 0x02, 0x14, 0xc3, 0x3e, 0x72, - 0x3a, 0x5d, 0xd5, 0x23, 0xfc, 0x14, 0x5f, 0xc0 }, - { 0x81, 0xe9, 0x2b, 0x6c, 0x0e, 0xe0, 0xe1, 0x2e, - 0xbc, 0xeb, 0xa8, 0xd9, 0x2a, 0x99, 0xdf, 0xa5 }, - { 0x98, 0x1d, 0x46, 0x4c, 0x7c, 0x52, 0xeb, 0x6e, - 0x50, 0x36, 0x23, 0x49, 0x84, 0xad, 0x0b, 0xcf }, - { 0x8a, 0x3b, 0x8d, 0x17 }, - { 0x28, 0xd7, 0xb0, 0xf2 }, - { 0x9a, 0x8d, 0x0e, 0x88, 0x3f, 0xf0, 0x88, 0x7a } - }, { - /* 3GPP TS 55.205 v6.0.0 - Test Set 19 */ - { 0x90, 0xdc, 0xa4, 0xed, 0xa4, 0x5b, 0x53, 0xcf, - 0x0f, 0x12, 0xd7, 0xc9, 0xc3, 0xbc, 0x6a, 0x89 }, - { 0x9f, 0xdd, 0xc7, 0x20, 0x92, 0xc6, 0xad, 0x03, - 0x6b, 0x6e, 0x46, 0x47, 0x89, 0x31, 0x5b, 0x78 }, - { 0xcb, 0x9c, 0xcc, 0xc4, 0xb9, 0x25, 0x8e, 0x6d, - 0xca, 0x47, 0x60, 0x37, 0x9f, 0xb8, 0x25, 0x81 }, - { 0xdf, 0x58, 0x52, 0x2f }, - { 0xa9, 0x51, 0x00, 0xe2 }, - { 0xed, 0x29, 0xb2, 0xf1, 0xc2, 0x7f, 0x9f, 0x34 } - } -}; - -#define NUM_GSM_TESTS (sizeof(gsm_test_sets) / sizeof(gsm_test_sets[0])) - - -struct milenage_test_set { - u8 k[16]; - u8 rand[16]; - u8 sqn[6]; - u8 amf[2]; - u8 op[16]; - u8 opc[16]; - u8 f1[8]; - u8 f1star[8]; - u8 f2[8]; - u8 f3[16]; - u8 f4[16]; - u8 f5[6]; - u8 f5star[6]; -}; - -static const struct milenage_test_set test_sets[] = -{ - { - /* 3GPP TS 35.208 v6.0.0 - 4.3.1 Test Set 1 */ - { 0x46, 0x5b, 0x5c, 0xe8, 0xb1, 0x99, 0xb4, 0x9f, - 0xaa, 0x5f, 0x0a, 0x2e, 0xe2, 0x38, 0xa6, 0xbc }, - { 0x23, 0x55, 0x3c, 0xbe, 0x96, 0x37, 0xa8, 0x9d, - 0x21, 0x8a, 0xe6, 0x4d, 0xae, 0x47, 0xbf, 0x35 }, - { 0xff, 0x9b, 0xb4, 0xd0, 0xb6, 0x07 }, - { 0xb9, 0xb9 }, - { 0xcd, 0xc2, 0x02, 0xd5, 0x12, 0x3e, 0x20, 0xf6, - 0x2b, 0x6d, 0x67, 0x6a, 0xc7, 0x2c, 0xb3, 0x18 }, - { 0xcd, 0x63, 0xcb, 0x71, 0x95, 0x4a, 0x9f, 0x4e, - 0x48, 0xa5, 0x99, 0x4e, 0x37, 0xa0, 0x2b, 0xaf }, - { 0x4a, 0x9f, 0xfa, 0xc3, 0x54, 0xdf, 0xaf, 0xb3 }, - { 0x01, 0xcf, 0xaf, 0x9e, 0xc4, 0xe8, 0x71, 0xe9 }, - { 0xa5, 0x42, 0x11, 0xd5, 0xe3, 0xba, 0x50, 0xbf }, - { 0xb4, 0x0b, 0xa9, 0xa3, 0xc5, 0x8b, 0x2a, 0x05, - 0xbb, 0xf0, 0xd9, 0x87, 0xb2, 0x1b, 0xf8, 0xcb }, - { 0xf7, 0x69, 0xbc, 0xd7, 0x51, 0x04, 0x46, 0x04, - 0x12, 0x76, 0x72, 0x71, 0x1c, 0x6d, 0x34, 0x41 }, - { 0xaa, 0x68, 0x9c, 0x64, 0x83, 0x70 }, - { 0x45, 0x1e, 0x8b, 0xec, 0xa4, 0x3b } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.2 Test Set 2 */ - { 0x46, 0x5b, 0x5c, 0xe8, 0xb1, 0x99, 0xb4, 0x9f, - 0xaa, 0x5f, 0x0a, 0x2e, 0xe2, 0x38, 0xa6, 0xbc }, - { 0x23, 0x55, 0x3c, 0xbe, 0x96, 0x37, 0xa8, 0x9d, - 0x21, 0x8a, 0xe6, 0x4d, 0xae, 0x47, 0xbf, 0x35 }, - { 0xff, 0x9b, 0xb4, 0xd0, 0xb6, 0x07 }, - { 0xb9, 0xb9 }, - { 0xcd, 0xc2, 0x02, 0xd5, 0x12, 0x3e, 0x20, 0xf6, - 0x2b, 0x6d, 0x67, 0x6a, 0xc7, 0x2c, 0xb3, 0x18 }, - { 0xcd, 0x63, 0xcb, 0x71, 0x95, 0x4a, 0x9f, 0x4e, - 0x48, 0xa5, 0x99, 0x4e, 0x37, 0xa0, 0x2b, 0xaf }, - { 0x4a, 0x9f, 0xfa, 0xc3, 0x54, 0xdf, 0xaf, 0xb3 }, - { 0x01, 0xcf, 0xaf, 0x9e, 0xc4, 0xe8, 0x71, 0xe9 }, - { 0xa5, 0x42, 0x11, 0xd5, 0xe3, 0xba, 0x50, 0xbf }, - { 0xb4, 0x0b, 0xa9, 0xa3, 0xc5, 0x8b, 0x2a, 0x05, - 0xbb, 0xf0, 0xd9, 0x87, 0xb2, 0x1b, 0xf8, 0xcb }, - { 0xf7, 0x69, 0xbc, 0xd7, 0x51, 0x04, 0x46, 0x04, - 0x12, 0x76, 0x72, 0x71, 0x1c, 0x6d, 0x34, 0x41 }, - { 0xaa, 0x68, 0x9c, 0x64, 0x83, 0x70 }, - { 0x45, 0x1e, 0x8b, 0xec, 0xa4, 0x3b } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.3 Test Set 3 */ - { 0xfe, 0xc8, 0x6b, 0xa6, 0xeb, 0x70, 0x7e, 0xd0, - 0x89, 0x05, 0x75, 0x7b, 0x1b, 0xb4, 0x4b, 0x8f }, - { 0x9f, 0x7c, 0x8d, 0x02, 0x1a, 0xcc, 0xf4, 0xdb, - 0x21, 0x3c, 0xcf, 0xf0, 0xc7, 0xf7, 0x1a, 0x6a }, - { 0x9d, 0x02, 0x77, 0x59, 0x5f, 0xfc }, - { 0x72, 0x5c }, - { 0xdb, 0xc5, 0x9a, 0xdc, 0xb6, 0xf9, 0xa0, 0xef, - 0x73, 0x54, 0x77, 0xb7, 0xfa, 0xdf, 0x83, 0x74 }, - { 0x10, 0x06, 0x02, 0x0f, 0x0a, 0x47, 0x8b, 0xf6, - 0xb6, 0x99, 0xf1, 0x5c, 0x06, 0x2e, 0x42, 0xb3 }, - { 0x9c, 0xab, 0xc3, 0xe9, 0x9b, 0xaf, 0x72, 0x81 }, - { 0x95, 0x81, 0x4b, 0xa2, 0xb3, 0x04, 0x43, 0x24 }, - { 0x80, 0x11, 0xc4, 0x8c, 0x0c, 0x21, 0x4e, 0xd2 }, - { 0x5d, 0xbd, 0xbb, 0x29, 0x54, 0xe8, 0xf3, 0xcd, - 0xe6, 0x65, 0xb0, 0x46, 0x17, 0x9a, 0x50, 0x98 }, - { 0x59, 0xa9, 0x2d, 0x3b, 0x47, 0x6a, 0x04, 0x43, - 0x48, 0x70, 0x55, 0xcf, 0x88, 0xb2, 0x30, 0x7b }, - { 0x33, 0x48, 0x4d, 0xc2, 0x13, 0x6b }, - { 0xde, 0xac, 0xdd, 0x84, 0x8c, 0xc6 } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.4 Test Set 4 */ - { 0x9e, 0x59, 0x44, 0xae, 0xa9, 0x4b, 0x81, 0x16, - 0x5c, 0x82, 0xfb, 0xf9, 0xf3, 0x2d, 0xb7, 0x51 }, - { 0xce, 0x83, 0xdb, 0xc5, 0x4a, 0xc0, 0x27, 0x4a, - 0x15, 0x7c, 0x17, 0xf8, 0x0d, 0x01, 0x7b, 0xd6 }, - { 0x0b, 0x60, 0x4a, 0x81, 0xec, 0xa8 }, - { 0x9e, 0x09 }, - { 0x22, 0x30, 0x14, 0xc5, 0x80, 0x66, 0x94, 0xc0, - 0x07, 0xca, 0x1e, 0xee, 0xf5, 0x7f, 0x00, 0x4f }, - { 0xa6, 0x4a, 0x50, 0x7a, 0xe1, 0xa2, 0xa9, 0x8b, - 0xb8, 0x8e, 0xb4, 0x21, 0x01, 0x35, 0xdc, 0x87 }, - { 0x74, 0xa5, 0x82, 0x20, 0xcb, 0xa8, 0x4c, 0x49 }, - { 0xac, 0x2c, 0xc7, 0x4a, 0x96, 0x87, 0x18, 0x37 }, - { 0xf3, 0x65, 0xcd, 0x68, 0x3c, 0xd9, 0x2e, 0x96 }, - { 0xe2, 0x03, 0xed, 0xb3, 0x97, 0x15, 0x74, 0xf5, - 0xa9, 0x4b, 0x0d, 0x61, 0xb8, 0x16, 0x34, 0x5d }, - { 0x0c, 0x45, 0x24, 0xad, 0xea, 0xc0, 0x41, 0xc4, - 0xdd, 0x83, 0x0d, 0x20, 0x85, 0x4f, 0xc4, 0x6b }, - { 0xf0, 0xb9, 0xc0, 0x8a, 0xd0, 0x2e }, - { 0x60, 0x85, 0xa8, 0x6c, 0x6f, 0x63 } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.5 Test Set 5 */ - { 0x4a, 0xb1, 0xde, 0xb0, 0x5c, 0xa6, 0xce, 0xb0, - 0x51, 0xfc, 0x98, 0xe7, 0x7d, 0x02, 0x6a, 0x84 }, - { 0x74, 0xb0, 0xcd, 0x60, 0x31, 0xa1, 0xc8, 0x33, - 0x9b, 0x2b, 0x6c, 0xe2, 0xb8, 0xc4, 0xa1, 0x86 }, - { 0xe8, 0x80, 0xa1, 0xb5, 0x80, 0xb6 }, - { 0x9f, 0x07 }, - { 0x2d, 0x16, 0xc5, 0xcd, 0x1f, 0xdf, 0x6b, 0x22, - 0x38, 0x35, 0x84, 0xe3, 0xbe, 0xf2, 0xa8, 0xd8 }, - { 0xdc, 0xf0, 0x7c, 0xbd, 0x51, 0x85, 0x52, 0x90, - 0xb9, 0x2a, 0x07, 0xa9, 0x89, 0x1e, 0x52, 0x3e }, - { 0x49, 0xe7, 0x85, 0xdd, 0x12, 0x62, 0x6e, 0xf2 }, - { 0x9e, 0x85, 0x79, 0x03, 0x36, 0xbb, 0x3f, 0xa2 }, - { 0x58, 0x60, 0xfc, 0x1b, 0xce, 0x35, 0x1e, 0x7e }, - { 0x76, 0x57, 0x76, 0x6b, 0x37, 0x3d, 0x1c, 0x21, - 0x38, 0xf3, 0x07, 0xe3, 0xde, 0x92, 0x42, 0xf9 }, - { 0x1c, 0x42, 0xe9, 0x60, 0xd8, 0x9b, 0x8f, 0xa9, - 0x9f, 0x27, 0x44, 0xe0, 0x70, 0x8c, 0xcb, 0x53 }, - { 0x31, 0xe1, 0x1a, 0x60, 0x91, 0x18 }, - { 0xfe, 0x25, 0x55, 0xe5, 0x4a, 0xa9 } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.6 Test Set 6 */ - { 0x6c, 0x38, 0xa1, 0x16, 0xac, 0x28, 0x0c, 0x45, - 0x4f, 0x59, 0x33, 0x2e, 0xe3, 0x5c, 0x8c, 0x4f }, - { 0xee, 0x64, 0x66, 0xbc, 0x96, 0x20, 0x2c, 0x5a, - 0x55, 0x7a, 0xbb, 0xef, 0xf8, 0xba, 0xbf, 0x63 }, - { 0x41, 0x4b, 0x98, 0x22, 0x21, 0x81 }, - { 0x44, 0x64 }, - { 0x1b, 0xa0, 0x0a, 0x1a, 0x7c, 0x67, 0x00, 0xac, - 0x8c, 0x3f, 0xf3, 0xe9, 0x6a, 0xd0, 0x87, 0x25 }, - { 0x38, 0x03, 0xef, 0x53, 0x63, 0xb9, 0x47, 0xc6, - 0xaa, 0xa2, 0x25, 0xe5, 0x8f, 0xae, 0x39, 0x34 }, - { 0x07, 0x8a, 0xdf, 0xb4, 0x88, 0x24, 0x1a, 0x57 }, - { 0x80, 0x24, 0x6b, 0x8d, 0x01, 0x86, 0xbc, 0xf1 }, - { 0x16, 0xc8, 0x23, 0x3f, 0x05, 0xa0, 0xac, 0x28 }, - { 0x3f, 0x8c, 0x75, 0x87, 0xfe, 0x8e, 0x4b, 0x23, - 0x3a, 0xf6, 0x76, 0xae, 0xde, 0x30, 0xba, 0x3b }, - { 0xa7, 0x46, 0x6c, 0xc1, 0xe6, 0xb2, 0xa1, 0x33, - 0x7d, 0x49, 0xd3, 0xb6, 0x6e, 0x95, 0xd7, 0xb4 }, - { 0x45, 0xb0, 0xf6, 0x9a, 0xb0, 0x6c }, - { 0x1f, 0x53, 0xcd, 0x2b, 0x11, 0x13 } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.7 Test Set 7 */ - { 0x2d, 0x60, 0x9d, 0x4d, 0xb0, 0xac, 0x5b, 0xf0, - 0xd2, 0xc0, 0xde, 0x26, 0x70, 0x14, 0xde, 0x0d }, - { 0x19, 0x4a, 0xa7, 0x56, 0x01, 0x38, 0x96, 0xb7, - 0x4b, 0x4a, 0x2a, 0x3b, 0x0a, 0xf4, 0x53, 0x9e }, - { 0x6b, 0xf6, 0x94, 0x38, 0xc2, 0xe4 }, - { 0x5f, 0x67 }, - { 0x46, 0x0a, 0x48, 0x38, 0x54, 0x27, 0xaa, 0x39, - 0x26, 0x4a, 0xac, 0x8e, 0xfc, 0x9e, 0x73, 0xe8 }, - { 0xc3, 0x5a, 0x0a, 0xb0, 0xbc, 0xbf, 0xc9, 0x25, - 0x2c, 0xaf, 0xf1, 0x5f, 0x24, 0xef, 0xbd, 0xe0 }, - { 0xbd, 0x07, 0xd3, 0x00, 0x3b, 0x9e, 0x5c, 0xc3 }, - { 0xbc, 0xb6, 0xc2, 0xfc, 0xad, 0x15, 0x22, 0x50 }, - { 0x8c, 0x25, 0xa1, 0x6c, 0xd9, 0x18, 0xa1, 0xdf }, - { 0x4c, 0xd0, 0x84, 0x60, 0x20, 0xf8, 0xfa, 0x07, - 0x31, 0xdd, 0x47, 0xcb, 0xdc, 0x6b, 0xe4, 0x11 }, - { 0x88, 0xab, 0x80, 0xa4, 0x15, 0xf1, 0x5c, 0x73, - 0x71, 0x12, 0x54, 0xa1, 0xd3, 0x88, 0xf6, 0x96 }, - { 0x7e, 0x64, 0x55, 0xf3, 0x4c, 0xf3 }, - { 0xdc, 0x6d, 0xd0, 0x1e, 0x8f, 0x15 } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.8 Test Set 8 */ - { 0xa5, 0x30, 0xa7, 0xfe, 0x42, 0x8f, 0xad, 0x10, - 0x82, 0xc4, 0x5e, 0xdd, 0xfc, 0xe1, 0x38, 0x84 }, - { 0x3a, 0x4c, 0x2b, 0x32, 0x45, 0xc5, 0x0e, 0xb5, - 0xc7, 0x1d, 0x08, 0x63, 0x93, 0x95, 0x76, 0x4d }, - { 0xf6, 0x3f, 0x5d, 0x76, 0x87, 0x84 }, - { 0xb9, 0x0e }, - { 0x51, 0x1c, 0x6c, 0x4e, 0x83, 0xe3, 0x8c, 0x89, - 0xb1, 0xc5, 0xd8, 0xdd, 0xe6, 0x24, 0x26, 0xfa }, - { 0x27, 0x95, 0x3e, 0x49, 0xbc, 0x8a, 0xf6, 0xdc, - 0xc6, 0xe7, 0x30, 0xeb, 0x80, 0x28, 0x6b, 0xe3 }, - { 0x53, 0x76, 0x1f, 0xbd, 0x67, 0x9b, 0x0b, 0xad }, - { 0x21, 0xad, 0xfd, 0x33, 0x4a, 0x10, 0xe7, 0xce }, - { 0xa6, 0x32, 0x41, 0xe1, 0xff, 0xc3, 0xe5, 0xab }, - { 0x10, 0xf0, 0x5b, 0xab, 0x75, 0xa9, 0x9a, 0x5f, - 0xbb, 0x98, 0xa9, 0xc2, 0x87, 0x67, 0x9c, 0x3b }, - { 0xf9, 0xec, 0x08, 0x65, 0xeb, 0x32, 0xf2, 0x23, - 0x69, 0xca, 0xde, 0x40, 0xc5, 0x9c, 0x3a, 0x44 }, - { 0x88, 0x19, 0x6c, 0x47, 0x98, 0x6f }, - { 0xc9, 0x87, 0xa3, 0xd2, 0x31, 0x15 } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.9 Test Set 9 */ - { 0xd9, 0x15, 0x1c, 0xf0, 0x48, 0x96, 0xe2, 0x58, - 0x30, 0xbf, 0x2e, 0x08, 0x26, 0x7b, 0x83, 0x60 }, - { 0xf7, 0x61, 0xe5, 0xe9, 0x3d, 0x60, 0x3f, 0xeb, - 0x73, 0x0e, 0x27, 0x55, 0x6c, 0xb8, 0xa2, 0xca }, - { 0x47, 0xee, 0x01, 0x99, 0x82, 0x0a }, - { 0x91, 0x13 }, - { 0x75, 0xfc, 0x22, 0x33, 0xa4, 0x42, 0x94, 0xee, - 0x8e, 0x6d, 0xe2, 0x5c, 0x43, 0x53, 0xd2, 0x6b }, - { 0xc4, 0xc9, 0x3e, 0xff, 0xe8, 0xa0, 0x81, 0x38, - 0xc2, 0x03, 0xd4, 0xc2, 0x7c, 0xe4, 0xe3, 0xd9 }, - { 0x66, 0xcc, 0x4b, 0xe4, 0x48, 0x62, 0xaf, 0x1f }, - { 0x7a, 0x4b, 0x8d, 0x7a, 0x87, 0x53, 0xf2, 0x46 }, - { 0x4a, 0x90, 0xb2, 0x17, 0x1a, 0xc8, 0x3a, 0x76 }, - { 0x71, 0x23, 0x6b, 0x71, 0x29, 0xf9, 0xb2, 0x2a, - 0xb7, 0x7e, 0xa7, 0xa5, 0x4c, 0x96, 0xda, 0x22 }, - { 0x90, 0x52, 0x7e, 0xba, 0xa5, 0x58, 0x89, 0x68, - 0xdb, 0x41, 0x72, 0x73, 0x25, 0xa0, 0x4d, 0x9e }, - { 0x82, 0xa0, 0xf5, 0x28, 0x7a, 0x71 }, - { 0x52, 0x7d, 0xbf, 0x41, 0xf3, 0x5f } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.10 Test Set 10 */ - { 0xa0, 0xe2, 0x97, 0x1b, 0x68, 0x22, 0xe8, 0xd3, - 0x54, 0xa1, 0x8c, 0xc2, 0x35, 0x62, 0x4e, 0xcb }, - { 0x08, 0xef, 0xf8, 0x28, 0xb1, 0x3f, 0xdb, 0x56, - 0x27, 0x22, 0xc6, 0x5c, 0x7f, 0x30, 0xa9, 0xb2 }, - { 0xdb, 0x5c, 0x06, 0x64, 0x81, 0xe0 }, - { 0x71, 0x6b }, - { 0x32, 0x37, 0x92, 0xfa, 0xca, 0x21, 0xfb, 0x4d, - 0x5d, 0x6f, 0x13, 0xc1, 0x45, 0xa9, 0xd2, 0xc1 }, - { 0x82, 0xa2, 0x6f, 0x22, 0xbb, 0xa9, 0xe9, 0x48, - 0x8f, 0x94, 0x9a, 0x10, 0xd9, 0x8e, 0x9c, 0xc4 }, - { 0x94, 0x85, 0xfe, 0x24, 0x62, 0x1c, 0xb9, 0xf6 }, - { 0xbc, 0xe3, 0x25, 0xce, 0x03, 0xe2, 0xe9, 0xb9 }, - { 0x4b, 0xc2, 0x21, 0x2d, 0x86, 0x24, 0x91, 0x0a }, - { 0x08, 0xce, 0xf6, 0xd0, 0x04, 0xec, 0x61, 0x47, - 0x1a, 0x3c, 0x3c, 0xda, 0x04, 0x81, 0x37, 0xfa }, - { 0xed, 0x03, 0x18, 0xca, 0x5d, 0xeb, 0x92, 0x06, - 0x27, 0x2f, 0x6e, 0x8f, 0xa6, 0x4b, 0xa4, 0x11 }, - { 0xa2, 0xf8, 0x58, 0xaa, 0x9e, 0x5d }, - { 0x74, 0xe7, 0x6f, 0xbb, 0xec, 0x38 } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.11 Test Set 11 */ - { 0x0d, 0xa6, 0xf7, 0xba, 0x86, 0xd5, 0xea, 0xc8, - 0xa1, 0x9c, 0xf5, 0x63, 0xac, 0x58, 0x64, 0x2d }, - { 0x67, 0x9a, 0xc4, 0xdb, 0xac, 0xd7, 0xd2, 0x33, - 0xff, 0x9d, 0x68, 0x06, 0xf4, 0x14, 0x9c, 0xe3 }, - { 0x6e, 0x23, 0x31, 0xd6, 0x92, 0xad }, - { 0x22, 0x4a }, - { 0x4b, 0x9a, 0x26, 0xfa, 0x45, 0x9e, 0x3a, 0xcb, - 0xff, 0x36, 0xf4, 0x01, 0x5d, 0xe3, 0xbd, 0xc1 }, - { 0x0d, 0xb1, 0x07, 0x1f, 0x87, 0x67, 0x56, 0x2c, - 0xa4, 0x3a, 0x0a, 0x64, 0xc4, 0x1e, 0x8d, 0x08 }, - { 0x28, 0x31, 0xd7, 0xae, 0x90, 0x88, 0xe4, 0x92 }, - { 0x9b, 0x2e, 0x16, 0x95, 0x11, 0x35, 0xd5, 0x23 }, - { 0x6f, 0xc3, 0x0f, 0xee, 0x6d, 0x12, 0x35, 0x23 }, - { 0x69, 0xb1, 0xca, 0xe7, 0xc7, 0x42, 0x9d, 0x97, - 0x5e, 0x24, 0x5c, 0xac, 0xb0, 0x5a, 0x51, 0x7c }, - { 0x74, 0xf2, 0x4e, 0x8c, 0x26, 0xdf, 0x58, 0xe1, - 0xb3, 0x8d, 0x7d, 0xcd, 0x4f, 0x1b, 0x7f, 0xbd }, - { 0x4c, 0x53, 0x9a, 0x26, 0xe1, 0xfa }, - { 0x07, 0x86, 0x1e, 0x12, 0x69, 0x28 } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.12 Test Set 12 */ - { 0x77, 0xb4, 0x58, 0x43, 0xc8, 0x8e, 0x58, 0xc1, - 0x0d, 0x20, 0x26, 0x84, 0x51, 0x5e, 0xd4, 0x30 }, - { 0x4c, 0x47, 0xeb, 0x30, 0x76, 0xdc, 0x55, 0xfe, - 0x51, 0x06, 0xcb, 0x20, 0x34, 0xb8, 0xcd, 0x78 }, - { 0xfe, 0x1a, 0x87, 0x31, 0x00, 0x5d }, - { 0xad, 0x25 }, - { 0xbf, 0x32, 0x86, 0xc7, 0xa5, 0x14, 0x09, 0xce, - 0x95, 0x72, 0x4d, 0x50, 0x3b, 0xfe, 0x6e, 0x70 }, - { 0xd4, 0x83, 0xaf, 0xae, 0x56, 0x24, 0x09, 0xa3, - 0x26, 0xb5, 0xbb, 0x0b, 0x20, 0xc4, 0xd7, 0x62 }, - { 0x08, 0x33, 0x2d, 0x7e, 0x9f, 0x48, 0x45, 0x70 }, - { 0xed, 0x41, 0xb7, 0x34, 0x48, 0x9d, 0x52, 0x07 }, - { 0xae, 0xfa, 0x35, 0x7b, 0xea, 0xc2, 0xa8, 0x7a }, - { 0x90, 0x8c, 0x43, 0xf0, 0x56, 0x9c, 0xb8, 0xf7, - 0x4b, 0xc9, 0x71, 0xe7, 0x06, 0xc3, 0x6c, 0x5f }, - { 0xc2, 0x51, 0xdf, 0x0d, 0x88, 0x8d, 0xd9, 0x32, - 0x9b, 0xcf, 0x46, 0x65, 0x5b, 0x22, 0x6e, 0x40 }, - { 0x30, 0xff, 0x25, 0xcd, 0xad, 0xf6 }, - { 0xe8, 0x4e, 0xd0, 0xd4, 0x67, 0x7e } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.13 Test Set 13 */ - { 0x72, 0x9b, 0x17, 0x72, 0x92, 0x70, 0xdd, 0x87, - 0xcc, 0xdf, 0x1b, 0xfe, 0x29, 0xb4, 0xe9, 0xbb }, - { 0x31, 0x1c, 0x4c, 0x92, 0x97, 0x44, 0xd6, 0x75, - 0xb7, 0x20, 0xf3, 0xb7, 0xe9, 0xb1, 0xcb, 0xd0 }, - { 0xc8, 0x5c, 0x4c, 0xf6, 0x59, 0x16 }, - { 0x5b, 0xb2 }, - { 0xd0, 0x4c, 0x9c, 0x35, 0xbd, 0x22, 0x62, 0xfa, - 0x81, 0x0d, 0x29, 0x24, 0xd0, 0x36, 0xfd, 0x13 }, - { 0x22, 0x8c, 0x2f, 0x2f, 0x06, 0xac, 0x32, 0x68, - 0xa9, 0xe6, 0x16, 0xee, 0x16, 0xdb, 0x4b, 0xa1 }, - { 0xff, 0x79, 0x4f, 0xe2, 0xf8, 0x27, 0xeb, 0xf8 }, - { 0x24, 0xfe, 0x4d, 0xc6, 0x1e, 0x87, 0x4b, 0x52 }, - { 0x98, 0xdb, 0xbd, 0x09, 0x9b, 0x3b, 0x40, 0x8d }, - { 0x44, 0xc0, 0xf2, 0x3c, 0x54, 0x93, 0xcf, 0xd2, - 0x41, 0xe4, 0x8f, 0x19, 0x7e, 0x1d, 0x10, 0x12 }, - { 0x0c, 0x9f, 0xb8, 0x16, 0x13, 0x88, 0x4c, 0x25, - 0x35, 0xdd, 0x0e, 0xab, 0xf3, 0xb4, 0x40, 0xd8 }, - { 0x53, 0x80, 0xd1, 0x58, 0xcf, 0xe3 }, - { 0x87, 0xac, 0x3b, 0x55, 0x9f, 0xb6 } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.14 Test Set 14 */ - { 0xd3, 0x2d, 0xd2, 0x3e, 0x89, 0xdc, 0x66, 0x23, - 0x54, 0xca, 0x12, 0xeb, 0x79, 0xdd, 0x32, 0xfa }, - { 0xcf, 0x7d, 0x0a, 0xb1, 0xd9, 0x43, 0x06, 0x95, - 0x0b, 0xf1, 0x20, 0x18, 0xfb, 0xd4, 0x68, 0x87 }, - { 0x48, 0x41, 0x07, 0xe5, 0x6a, 0x43 }, - { 0xb5, 0xe6 }, - { 0xfe, 0x75, 0x90, 0x5b, 0x9d, 0xa4, 0x7d, 0x35, - 0x62, 0x36, 0xd0, 0x31, 0x4e, 0x09, 0xc3, 0x2e }, - { 0xd2, 0x2a, 0x4b, 0x41, 0x80, 0xa5, 0x32, 0x57, - 0x08, 0xa5, 0xff, 0x70, 0xd9, 0xf6, 0x7e, 0xc7 }, - { 0xcf, 0x19, 0xd6, 0x2b, 0x6a, 0x80, 0x98, 0x66 }, - { 0x5d, 0x26, 0x95, 0x37, 0xe4, 0x5e, 0x2c, 0xe6 }, - { 0xaf, 0x4a, 0x41, 0x1e, 0x11, 0x39, 0xf2, 0xc2 }, - { 0x5a, 0xf8, 0x6b, 0x80, 0xed, 0xb7, 0x0d, 0xf5, - 0x29, 0x2c, 0xc1, 0x12, 0x1c, 0xba, 0xd5, 0x0c }, - { 0x7f, 0x4d, 0x6a, 0xe7, 0x44, 0x0e, 0x18, 0x78, - 0x9a, 0x8b, 0x75, 0xad, 0x3f, 0x42, 0xf0, 0x3a }, - { 0x21, 0x7a, 0xf4, 0x92, 0x72, 0xad }, - { 0x90, 0x0e, 0x10, 0x1c, 0x67, 0x7e } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.15 Test Set 15 */ - { 0xaf, 0x7c, 0x65, 0xe1, 0x92, 0x72, 0x21, 0xde, - 0x59, 0x11, 0x87, 0xa2, 0xc5, 0x98, 0x7a, 0x53 }, - { 0x1f, 0x0f, 0x85, 0x78, 0x46, 0x4f, 0xd5, 0x9b, - 0x64, 0xbe, 0xd2, 0xd0, 0x94, 0x36, 0xb5, 0x7a }, - { 0x3d, 0x62, 0x7b, 0x01, 0x41, 0x8d }, - { 0x84, 0xf6 }, - { 0x0c, 0x7a, 0xcb, 0x8d, 0x95, 0xb7, 0xd4, 0xa3, - 0x1c, 0x5a, 0xca, 0x6d, 0x26, 0x34, 0x5a, 0x88 }, - { 0xa4, 0xcf, 0x5c, 0x81, 0x55, 0xc0, 0x8a, 0x7e, - 0xff, 0x41, 0x8e, 0x54, 0x43, 0xb9, 0x8e, 0x55 }, - { 0xc3, 0x7c, 0xae, 0x78, 0x05, 0x64, 0x20, 0x32 }, - { 0x68, 0xcd, 0x09, 0xa4, 0x52, 0xd8, 0xdb, 0x7c }, - { 0x7b, 0xff, 0xa5, 0xc2, 0xf4, 0x1f, 0xbc, 0x05 }, - { 0x3f, 0x8c, 0x3f, 0x3c, 0xcf, 0x76, 0x25, 0xbf, - 0x77, 0xfc, 0x94, 0xbc, 0xfd, 0x22, 0xfd, 0x26 }, - { 0xab, 0xcb, 0xae, 0x8f, 0xd4, 0x61, 0x15, 0xe9, - 0x96, 0x1a, 0x55, 0xd0, 0xda, 0x5f, 0x20, 0x78 }, - { 0x83, 0x7f, 0xd7, 0xb7, 0x44, 0x19 }, - { 0x56, 0xe9, 0x7a, 0x60, 0x90, 0xb1 } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.16 Test Set 16 */ - { 0x5b, 0xd7, 0xec, 0xd3, 0xd3, 0x12, 0x7a, 0x41, - 0xd1, 0x25, 0x39, 0xbe, 0xd4, 0xe7, 0xcf, 0x71 }, - { 0x59, 0xb7, 0x5f, 0x14, 0x25, 0x1c, 0x75, 0x03, - 0x1d, 0x0b, 0xcb, 0xac, 0x1c, 0x2c, 0x04, 0xc7 }, - { 0xa2, 0x98, 0xae, 0x89, 0x29, 0xdc }, - { 0xd0, 0x56 }, - { 0xf9, 0x67, 0xf7, 0x60, 0x38, 0xb9, 0x20, 0xa9, - 0xcd, 0x25, 0xe1, 0x0c, 0x08, 0xb4, 0x99, 0x24 }, - { 0x76, 0x08, 0x9d, 0x3c, 0x0f, 0xf3, 0xef, 0xdc, - 0x6e, 0x36, 0x72, 0x1d, 0x4f, 0xce, 0xb7, 0x47 }, - { 0xc3, 0xf2, 0x5c, 0xd9, 0x43, 0x09, 0x10, 0x7e }, - { 0xb0, 0xc8, 0xba, 0x34, 0x36, 0x65, 0xaf, 0xcc }, - { 0x7e, 0x3f, 0x44, 0xc7, 0x59, 0x1f, 0x6f, 0x45 }, - { 0xd4, 0x2b, 0x2d, 0x61, 0x5e, 0x49, 0xa0, 0x3a, - 0xc2, 0x75, 0xa5, 0xae, 0xf9, 0x7a, 0xf8, 0x92 }, - { 0x0b, 0x3f, 0x8d, 0x02, 0x4f, 0xe6, 0xbf, 0xaf, - 0xaa, 0x98, 0x2b, 0x8f, 0x82, 0xe3, 0x19, 0xc2 }, - { 0x5b, 0xe1, 0x14, 0x95, 0x52, 0x5d }, - { 0x4d, 0x6a, 0x34, 0xa1, 0xe4, 0xeb } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.17 Test Set 17 */ - { 0x6c, 0xd1, 0xc6, 0xce, 0xb1, 0xe0, 0x1e, 0x14, - 0xf1, 0xb8, 0x23, 0x16, 0xa9, 0x0b, 0x7f, 0x3d }, - { 0xf6, 0x9b, 0x78, 0xf3, 0x00, 0xa0, 0x56, 0x8b, - 0xce, 0x9f, 0x0c, 0xb9, 0x3c, 0x4b, 0xe4, 0xc9 }, - { 0xb4, 0xfc, 0xe5, 0xfe, 0xb0, 0x59 }, - { 0xe4, 0xbb }, - { 0x07, 0x8b, 0xfc, 0xa9, 0x56, 0x46, 0x59, 0xec, - 0xd8, 0x85, 0x1e, 0x84, 0xe6, 0xc5, 0x9b, 0x48 }, - { 0xa2, 0x19, 0xdc, 0x37, 0xf1, 0xdc, 0x7d, 0x66, - 0x73, 0x8b, 0x58, 0x43, 0xc7, 0x99, 0xf2, 0x06 }, - { 0x69, 0xa9, 0x08, 0x69, 0xc2, 0x68, 0xcb, 0x7b }, - { 0x2e, 0x0f, 0xdc, 0xf9, 0xfd, 0x1c, 0xfa, 0x6a }, - { 0x70, 0xf6, 0xbd, 0xb9, 0xad, 0x21, 0x52, 0x5f }, - { 0x6e, 0xda, 0xf9, 0x9e, 0x5b, 0xd9, 0xf8, 0x5d, - 0x5f, 0x36, 0xd9, 0x1c, 0x12, 0x72, 0xfb, 0x4b }, - { 0xd6, 0x1c, 0x85, 0x3c, 0x28, 0x0d, 0xd9, 0xc4, - 0x6f, 0x29, 0x7b, 0xae, 0xc3, 0x86, 0xde, 0x17 }, - { 0x1c, 0x40, 0x8a, 0x85, 0x8b, 0x3e }, - { 0xaa, 0x4a, 0xe5, 0x2d, 0xaa, 0x30 } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.18 Test Set 18 */ - { 0xb7, 0x3a, 0x90, 0xcb, 0xcf, 0x3a, 0xfb, 0x62, - 0x2d, 0xba, 0x83, 0xc5, 0x8a, 0x84, 0x15, 0xdf }, - { 0xb1, 0x20, 0xf1, 0xc1, 0xa0, 0x10, 0x2a, 0x2f, - 0x50, 0x7d, 0xd5, 0x43, 0xde, 0x68, 0x28, 0x1f }, - { 0xf1, 0xe8, 0xa5, 0x23, 0xa3, 0x6d }, - { 0x47, 0x1b }, - { 0xb6, 0x72, 0x04, 0x7e, 0x00, 0x3b, 0xb9, 0x52, - 0xdc, 0xa6, 0xcb, 0x8a, 0xf0, 0xe5, 0xb7, 0x79 }, - { 0xdf, 0x0c, 0x67, 0x86, 0x8f, 0xa2, 0x5f, 0x74, - 0x8b, 0x70, 0x44, 0xc6, 0xe7, 0xc2, 0x45, 0xb8 }, - { 0xeb, 0xd7, 0x03, 0x41, 0xbc, 0xd4, 0x15, 0xb0 }, - { 0x12, 0x35, 0x9f, 0x5d, 0x82, 0x22, 0x0c, 0x14 }, - { 0x47, 0x9d, 0xd2, 0x5c, 0x20, 0x79, 0x2d, 0x63 }, - { 0x66, 0x19, 0x5d, 0xbe, 0xd0, 0x31, 0x32, 0x74, - 0xc5, 0xca, 0x77, 0x66, 0x61, 0x5f, 0xa2, 0x5e }, - { 0x66, 0xbe, 0xc7, 0x07, 0xeb, 0x2a, 0xfc, 0x47, - 0x6d, 0x74, 0x08, 0xa8, 0xf2, 0x92, 0x7b, 0x36 }, - { 0xae, 0xfd, 0xaa, 0x5d, 0xdd, 0x99 }, - { 0x12, 0xec, 0x2b, 0x87, 0xfb, 0xb1 } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.19 Test Set 19 */ - { 0x51, 0x22, 0x25, 0x02, 0x14, 0xc3, 0x3e, 0x72, - 0x3a, 0x5d, 0xd5, 0x23, 0xfc, 0x14, 0x5f, 0xc0 }, - { 0x81, 0xe9, 0x2b, 0x6c, 0x0e, 0xe0, 0xe1, 0x2e, - 0xbc, 0xeb, 0xa8, 0xd9, 0x2a, 0x99, 0xdf, 0xa5 }, - { 0x16, 0xf3, 0xb3, 0xf7, 0x0f, 0xc2 }, - { 0xc3, 0xab }, - { 0xc9, 0xe8, 0x76, 0x32, 0x86, 0xb5, 0xb9, 0xff, - 0xbd, 0xf5, 0x6e, 0x12, 0x97, 0xd0, 0x88, 0x7b }, - { 0x98, 0x1d, 0x46, 0x4c, 0x7c, 0x52, 0xeb, 0x6e, - 0x50, 0x36, 0x23, 0x49, 0x84, 0xad, 0x0b, 0xcf }, - { 0x2a, 0x5c, 0x23, 0xd1, 0x5e, 0xe3, 0x51, 0xd5 }, - { 0x62, 0xda, 0xe3, 0x85, 0x3f, 0x3a, 0xf9, 0xd2 }, - { 0x28, 0xd7, 0xb0, 0xf2, 0xa2, 0xec, 0x3d, 0xe5 }, - { 0x53, 0x49, 0xfb, 0xe0, 0x98, 0x64, 0x9f, 0x94, - 0x8f, 0x5d, 0x2e, 0x97, 0x3a, 0x81, 0xc0, 0x0f }, - { 0x97, 0x44, 0x87, 0x1a, 0xd3, 0x2b, 0xf9, 0xbb, - 0xd1, 0xdd, 0x5c, 0xe5, 0x4e, 0x3e, 0x2e, 0x5a }, - { 0xad, 0xa1, 0x5a, 0xeb, 0x7b, 0xb8 }, - { 0xd4, 0x61, 0xbc, 0x15, 0x47, 0x5d } - }, { - /* 3GPP TS 35.208 v6.0.0 - 4.3.20 Test Set 20 */ - { 0x90, 0xdc, 0xa4, 0xed, 0xa4, 0x5b, 0x53, 0xcf, - 0x0f, 0x12, 0xd7, 0xc9, 0xc3, 0xbc, 0x6a, 0x89 }, - { 0x9f, 0xdd, 0xc7, 0x20, 0x92, 0xc6, 0xad, 0x03, - 0x6b, 0x6e, 0x46, 0x47, 0x89, 0x31, 0x5b, 0x78 }, - { 0x20, 0xf8, 0x13, 0xbd, 0x41, 0x41 }, - { 0x61, 0xdf }, - { 0x3f, 0xfc, 0xfe, 0x5b, 0x7b, 0x11, 0x11, 0x58, - 0x99, 0x20, 0xd3, 0x52, 0x8e, 0x84, 0xe6, 0x55 }, - { 0xcb, 0x9c, 0xcc, 0xc4, 0xb9, 0x25, 0x8e, 0x6d, - 0xca, 0x47, 0x60, 0x37, 0x9f, 0xb8, 0x25, 0x81 }, - { 0x09, 0xdb, 0x94, 0xea, 0xb4, 0xf8, 0x14, 0x9e }, - { 0xa2, 0x94, 0x68, 0xaa, 0x97, 0x75, 0xb5, 0x27 }, - { 0xa9, 0x51, 0x00, 0xe2, 0x76, 0x09, 0x52, 0xcd }, - { 0xb5, 0xf2, 0xda, 0x03, 0x88, 0x3b, 0x69, 0xf9, - 0x6b, 0xf5, 0x2e, 0x02, 0x9e, 0xd9, 0xac, 0x45 }, - { 0xb4, 0x72, 0x13, 0x68, 0xbc, 0x16, 0xea, 0x67, - 0x87, 0x5c, 0x55, 0x98, 0x68, 0x8b, 0xb0, 0xef }, - { 0x83, 0xcf, 0xd5, 0x4d, 0xb9, 0x13 }, - { 0x4f, 0x20, 0x39, 0x39, 0x2d, 0xdc } - } -}; - -#define NUM_TESTS (sizeof(test_sets) / sizeof(test_sets[0])) - - -int main(int argc, char *argv[]) -{ - u8 buf[16], buf2[16], buf3[16], buf4[16], buf5[16], opc[16]; - u8 auts[14], sqn[6], _rand[16]; - int ret = 0, res, i; - const struct milenage_test_set *t; - size_t res_len; - - wpa_debug_level = 0; - - printf("Milenage test sets\n"); - for (i = 0; i < NUM_TESTS; i++) { - t = &test_sets[i]; - printf("Test Set %d\n", i + 1); - - milenage_opc(t->op, t->k, opc); - if (memcmp(opc, t->opc, 16) != 0) { - printf("- milenage_opc failed\n"); - ret++; - } - - milenage_f1(opc, t->k, t->rand, t->sqn, t->amf, buf, buf2); - if (memcmp(buf, t->f1, 8) != 0) { - printf("- milenage_f1 failed\n"); - ret++; - } - if (memcmp(buf2, t->f1star, 8) != 0) { - printf("- milenage_f1* failed\n"); - ret++; - } - - milenage_f2345(opc, t->k, t->rand, buf, buf2, buf3, buf4, - buf5); - if (memcmp(buf, t->f2, 8) != 0) { - printf("- milenage_f2 failed\n"); - ret++; - } - if (memcmp(buf2, t->f3, 16) != 0) { - printf("- milenage_f3 failed\n"); - ret++; - } - if (memcmp(buf3, t->f4, 16) != 0) { - printf("- milenage_f4 failed\n"); - ret++; - } - if (memcmp(buf4, t->f5, 6) != 0) { - printf("- milenage_f5 failed\n"); - ret++; - } - if (memcmp(buf5, t->f5star, 6) != 0) { - printf("- milenage_f5* failed\n"); - ret++; - } - } - - printf("milenage_auts test:\n"); - memcpy(auts, "\x4f\x20\x39\x39\x2d\xdd", 6); - memcpy(auts + 6, "\x4b\xb4\x31\x6e\xd4\xa1\x46\x88", 8); - res = milenage_auts(t->opc, t->k, t->rand, auts, buf); - printf("AUTS for test set %d: %d / SQN=%02x%02x%02x%02x%02x%02x\n", - i, res, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); - if (res) - ret++; - - memset(_rand, 0xaa, sizeof(_rand)); - memcpy(auts, - "\x43\x68\x1a\xd3\xda\xf0\x06\xbc\xde\x40\x5a\x20\x72\x67", 14); - res = milenage_auts(t->opc, t->k, _rand, auts, buf); - printf("AUTS from a test USIM: %d / SQN=%02x%02x%02x%02x%02x%02x\n", - res, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); - if (res) - ret++; - - printf("milenage_generate test:\n"); - memcpy(sqn, "\x00\x00\x00\x00\x40\x44", 6); - memcpy(_rand, "\x12\x69\xb8\x23\x41\x39\x35\x66\xfb\x99\x41\xe9\x84" - "\x4f\xe6\x2f", 16); - res_len = 8; - milenage_generate(t->opc, t->amf, t->k, sqn, _rand, buf, buf2, buf3, - buf4, &res_len); - wpa_hexdump(MSG_DEBUG, "SQN", sqn, 6); - wpa_hexdump(MSG_DEBUG, "RAND", _rand, 16); - wpa_hexdump(MSG_DEBUG, "AUTN", buf, 16); - wpa_hexdump(MSG_DEBUG, "IK", buf2, 16); - wpa_hexdump(MSG_DEBUG, "CK", buf3, 16); - wpa_hexdump(MSG_DEBUG, "RES", buf4, res_len); - - printf("GSM-Milenage test sets\n"); - for (i = 0; i < NUM_GSM_TESTS; i++) { - const struct gsm_milenage_test_set *g; - u8 sres[4], kc[8]; - g = &gsm_test_sets[i]; - printf("Test Set %d\n", i + 1); - gsm_milenage(g->opc, g->ki, g->rand, sres, kc); - if (memcmp(g->kc, kc, 8) != 0) { - printf("- gsm_milenage Kc failed\n"); - ret++; - } -#ifdef GSM_MILENAGE_ALT_SRES - if (memcmp(g->sres2, sres, 4) != 0) { - printf("- gsm_milenage SRES#2 failed\n"); - ret++; - } -#else /* GSM_MILENAGE_ALT_SRES */ - if (memcmp(g->sres1, sres, 4) != 0) { - printf("- gsm_milenage SRES#1 failed\n"); - ret++; - } -#endif /* GSM_MILENAGE_ALT_SRES */ - } - - if (ret) - printf("Something failed\n"); - else - printf("OK\n"); - - return ret; -} -#endif /* TEST_MAIN_MILENAGE */ diff --git a/contrib/hostapd/milenage.h b/contrib/hostapd/milenage.h deleted file mode 100644 index cc184f0f025b..000000000000 --- a/contrib/hostapd/milenage.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * UMTS AKA - Milenage algorithm (3GPP TS 35.205, .206, .207, .208) - * Copyright (c) 2006 <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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); -void gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres, - u8 *kc); - -#endif /* MILENAGE_H */ diff --git a/contrib/hostapd/mlme.c b/contrib/hostapd/mlme.c deleted file mode 100644 index 3d4cf21a45b4..000000000000 --- a/contrib/hostapd/mlme.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * hostapd / IEEE 802.11 MLME - * Copyright 2003-2006, Jouni Malinen <j@w1.fi> - * 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 "includes.h" - -#include "hostapd.h" -#include "ieee802_11.h" -#include "sta_info.h" -#include "wpa.h" -#include "mlme.h" - - -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"; - } - - return "unknown"; -} - - -/** - * 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)); - 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)); - 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)); - 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/contrib/hostapd/mlme.h b/contrib/hostapd/mlme.h deleted file mode 100644 index c77a9390a8b6..000000000000 --- a/contrib/hostapd/mlme.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * hostapd / IEEE 802.11 MLME - * Copyright 2003, Jouni Malinen <j@w1.fi> - * 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/contrib/hostapd/ms_funcs.c b/contrib/hostapd/ms_funcs.c deleted file mode 100644 index d7231799d1c7..000000000000 --- a/contrib/hostapd/ms_funcs.c +++ /dev/null @@ -1,440 +0,0 @@ -/* - * WPA Supplicant / shared MSCHAPV2 helper functions / RFC 2433 / RFC 2759 - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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" -#include "rc4.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) - */ -static void 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; - - sha1_vector(3, addr, len, hash); - os_memcpy(challenge, hash, 8); -} - - -/** - * 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) - */ -void 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) - return; - - /* 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; - 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) - */ -void hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash) -{ - size_t len = 16; - 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_hallenge: 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) - */ -void 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); - nt_password_hash(password, password_len, password_hash); - challenge_response(challenge, password_hash, response); -} - - -/** - * generate_nt_response_pwhash - GenerateNTResponse() - RFC 2759, Sect. 8.1 - * @auth_challenge: 16-octet AuthenticatorChallenge (IN) - * @peer_hallenge: 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) - */ -void 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]; - - challenge_hash(peer_challenge, auth_challenge, username, username_len, - challenge); - challenge_response(challenge, password_hash, response); -} - - -/** - * 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>) - */ -void 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; - - hash_nt_password_hash(password_hash, password_hash_hash); - sha1_vector(3, addr1, len1, response); - - challenge_hash(peer_challenge, auth_challenge, username, username_len, - challenge); - 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>) - */ -void 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]; - nt_password_hash(password, password_len, password_hash); - 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) - */ -void nt_challenge_response(const u8 *challenge, const u8 *password, - size_t password_len, u8 *response) -{ - u8 password_hash[16]; - nt_password_hash(password, password_len, password_hash); - challenge_response(challenge, password_hash, response); -} - - -/** - * 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) - */ -void 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; - - sha1_vector(3, addr, len, hash); - os_memcpy(master_key, hash, 16); -} - - -/** - * 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) - */ -void 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; - - sha1_vector(4, addr, len, digest); - - if (session_key_len > SHA1_MAC_LEN) - session_key_len = SHA1_MAC_LEN; - os_memcpy(session_key, digest, session_key_len); -} - - -#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) - */ -static void 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; - - os_memset(pw_block, 0, PWBLOCK_LEN); - offset = (256 - password_len) * 2; - os_get_random(pw_block, offset); - 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(pw_block, PWBLOCK_LEN, password_hash, 16); -} - - -/** - * 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) - */ -void 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]; - - nt_password_hash(old_password, old_password_len, password_hash); - encrypt_pw_block_with_password_hash(new_password, new_password_len, - password_hash, encrypted_pw_block); -} - - -/** - * 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) - */ -static 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_ash: 16-octet EncryptedPasswordHash (OUT) - */ -void 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]; - - nt_password_hash(old_password, old_password_len, old_password_hash); - nt_password_hash(new_password, new_password_len, new_password_hash); - nt_password_hash_encrypted_with_block(old_password_hash, - new_password_hash, - encrypted_password_hash); -} diff --git a/contrib/hostapd/ms_funcs.h b/contrib/hostapd/ms_funcs.h deleted file mode 100644 index 8067c097214a..000000000000 --- a/contrib/hostapd/ms_funcs.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * WPA Supplicant / shared MSCHAPV2 helper functions / RFC 2433 / RFC 2759 - * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 - -void 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); -void 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); -void 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); -void 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); -void 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); -void nt_password_hash(const u8 *password, size_t password_len, - u8 *password_hash); -void hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash); -void get_master_key(const u8 *password_hash_hash, const u8 *nt_response, - u8 *master_key); -void get_asymetric_start_key(const u8 *master_key, u8 *session_key, - size_t session_key_len, int is_send, - int is_server); -void 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 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/contrib/hostapd/os.h b/contrib/hostapd/os.h deleted file mode 100644 index 25570a5e171a..000000000000 --- a/contrib/hostapd/os.h +++ /dev/null @@ -1,488 +0,0 @@ -/* - * wpa_supplicant/hostapd / OS specific functions - * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 */ - -#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_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_strdup -#ifdef _MSC_VER -#define os_strdup(s) _strdup(s) -#else -#define os_strdup(s) strdup(s) -#endif -#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 */ - - -#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/contrib/hostapd/os_internal.c b/contrib/hostapd/os_internal.c deleted file mode 100644 index b2183ea38f4d..000000000000 --- a/contrib/hostapd/os_internal.c +++ /dev/null @@ -1,441 +0,0 @@ -/* - * wpa_supplicant/hostapd / Internal implementation of OS specific functions - * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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; - } - - fread(buf, 1, *len, f); - 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; -} - - -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/contrib/hostapd/os_none.c b/contrib/hostapd/os_none.c deleted file mode 100644 index 7404e2293af5..000000000000 --- a/contrib/hostapd/os_none.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - * wpa_supplicant/hostapd / Empty OS specific functions - * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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; -} - - -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/contrib/hostapd/os_unix.c b/contrib/hostapd/os_unix.c deleted file mode 100644 index 69ba25a3e856..000000000000 --- a/contrib/hostapd/os_unix.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * wpa_supplicant/hostapd / OS specific functions for UNIX/POSIX systems - * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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" - -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; -} - - -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; - int last_errno; - - if (rel_path[0] == '/') - return strdup(rel_path); - - for (;;) { - buf = malloc(len); - if (buf == NULL) - return NULL; - cwd = getcwd(buf, len); - if (cwd == NULL) { - last_errno = errno; - free(buf); - if (last_errno != ERANGE) - return NULL; - len *= 2; - if (len > 2000) - return NULL; - } else { - buf[len - 1] = '\0'; - break; - } - } - - cwd_len = strlen(cwd); - rel_len = strlen(rel_path); - ret_len = cwd_len + 1 + rel_len + 1; - ret = malloc(ret_len); - if (ret) { - memcpy(ret, cwd, cwd_len); - ret[cwd_len] = '/'; - memcpy(ret + cwd_len + 1, rel_path, rel_len); - ret[ret_len - 1] = '\0'; - } - 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 = 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); -} diff --git a/contrib/hostapd/pmksa_cache.c b/contrib/hostapd/pmksa_cache.c deleted file mode 100644 index 0cb85233c836..000000000000 --- a/contrib/hostapd/pmksa_cache.c +++ /dev/null @@ -1,366 +0,0 @@ -/* - * hostapd - PMKSA cache for IEEE 802.11i RSN - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "hostapd.h" -#include "common.h" -#include "wpa.h" -#include "eloop.h" -#include "sha1.h" -#include "ieee802_1x.h" -#include "eapol_sm.h" -#include "pmksa_cache.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; -}; - - -/** - * rsn_pmkid - Calculate PMK identifier - * @pmk: Pairwise master key - * @pmk_len: Length of pmk in bytes - * @aa: Authenticator address - * @spa: Supplicant address - * - * 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) -{ - char *title = "PMK Name"; - const u8 *addr[3]; - const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN }; - unsigned char hash[SHA1_MAC_LEN]; - - addr[0] = (u8 *) title; - addr[1] = aa; - addr[2] = spa; - - hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash); - memcpy(pmkid, hash, PMKID_LEN); -} - - -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; - free(entry->identity); - ieee802_1x_free_radius_class(&entry->radius_class); - 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 = malloc(eapol->identity_len); - if (entry->identity) { - entry->identity_len = eapol->identity_len; - memcpy(entry->identity, eapol->identity, - eapol->identity_len); - } - } - - ieee802_1x_copy_radius_class(&entry->radius_class, - &eapol->radius_class); - - entry->eap_type_authsrv = eapol->eap_type_authsrv; - entry->vlan_id = 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) { - free(eapol->identity); - eapol->identity = malloc(entry->identity_len); - if (eapol->identity) { - eapol->identity_len = entry->identity_len; - memcpy(eapol->identity, entry->identity, - entry->identity_len); - } - wpa_hexdump_ascii(MSG_DEBUG, "STA identity from PMKSA", - eapol->identity, eapol->identity_len); - } - - ieee802_1x_free_radius_class(&eapol->radius_class); - ieee802_1x_copy_radius_class(&eapol->radius_class, - &entry->radius_class); - 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; - eapol->sta->vlan_id = entry->vlan_id; -} - - -/** - * 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 - * @session_timeout: Session timeout - * @eapol: Pointer to EAPOL state machine data - * 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_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) -{ - struct rsn_pmksa_cache_entry *entry, *pos, *prev; - struct os_time now; - - if (pmk_len > PMK_LEN) - return NULL; - - entry = wpa_zalloc(sizeof(*entry)); - if (entry == NULL) - return NULL; - memcpy(entry->pmk, pmk, pmk_len); - entry->pmk_len = pmk_len; - rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid); - os_get_time(&now); - entry->expiration = now.sec; - if (session_timeout > 0) - entry->expiration += session_timeout; - else - entry->expiration += dot11RSNAConfigPMKLifetime; - entry->akmp = WPA_KEY_MGMT_IEEE8021X; - 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_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); - } - - /* 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); - - 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; - 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; - free(pmksa); -} - - -/** - * pmksa_cache_get - Fetch a PMKSA cache entry - * @pmksa: Pointer to PMKSA cache data from pmksa_cache_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_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 || memcmp(entry->spa, spa, ETH_ALEN) == 0) && - (pmkid == NULL || - memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0)) - return entry; - entry = pmkid ? entry->hnext : entry->next; - } - return NULL; -} - - -/** - * 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 - * 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), void *ctx) -{ - struct rsn_pmksa_cache *pmksa; - - pmksa = wpa_zalloc(sizeof(*pmksa)); - if (pmksa) { - pmksa->free_cb = free_cb; - pmksa->ctx = ctx; - } - - return pmksa; -} diff --git a/contrib/hostapd/pmksa_cache.h b/contrib/hostapd/pmksa_cache.h deleted file mode 100644 index dd9074eefa94..000000000000 --- a/contrib/hostapd/pmksa_cache.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * hostapd - PMKSA cache for IEEE 802.11i RSN - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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, *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; -}; - -struct rsn_pmksa_cache; - -struct rsn_pmksa_cache * -pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry, - void *ctx), void *ctx); -void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa); -struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa, - const u8 *spa, const u8 *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, int session_timeout, - struct eapol_state_machine *eapol); -void pmksa_cache_to_eapol_data(struct rsn_pmksa_cache_entry *entry, - struct eapol_state_machine *eapol); -void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa, - u8 *pmkid); - -#endif /* PMKSA_CACHE_H */ diff --git a/contrib/hostapd/preauth.c b/contrib/hostapd/preauth.c deleted file mode 100644 index d9928815345a..000000000000 --- a/contrib/hostapd/preauth.c +++ /dev/null @@ -1,276 +0,0 @@ -/* - * hostapd - Authenticator for IEEE 802.11i RSN pre-authentication - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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_RSN_PREAUTH - -#include "hostapd.h" -#include "l2_packet.h" -#include "ieee802_1x.h" -#include "eloop.h" -#include "sta_info.h" -#include "wpa_common.h" -#include "eapol_sm.h" -#include "wpa.h" -#include "preauth.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; - - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "RSN: receive pre-auth packet " - "from interface '%s'\n", piface->ifname); - if (len < sizeof(*ethhdr) + sizeof(*hdr)) { - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "RSN: too short pre-auth " - "packet (len=%lu)\n", (unsigned long) len); - return; - } - - ethhdr = (struct l2_ethhdr *) buf; - hdr = (struct ieee802_1x_hdr *) (ethhdr + 1); - - if (memcmp(ethhdr->h_dest, hapd->own_addr, ETH_ALEN) != 0) { - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "RSN: pre-auth for " - "foreign address " MACSTR "\n", - MAC2STR(ethhdr->h_dest)); - return; - } - - sta = ap_get_sta(hapd, ethhdr->h_source); - if (sta && (sta->flags & WLAN_STA_ASSOC)) { - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "RSN: pre-auth for " - "already association STA " MACSTR "\n", - 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; - - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "RSN pre-auth interface '%s'\n", - ifname); - - piface = wpa_zalloc(sizeof(*piface)); - if (piface == NULL) - return -1; - piface->hapd = hapd; - - piface->ifname = 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) { - printf("Failed to open register layer 2 access to " - "ETH_P_PREAUTH\n"); - goto fail2; - } - - piface->next = hapd->preauth_iface; - hapd->preauth_iface = piface; - return 0; - -fail2: - free(piface->ifname); -fail1: - 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); - free(prev->ifname); - 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 = strdup(hapd->conf->rsn_preauth_interfaces); - if (tmp == NULL) - return -1; - start = tmp; - for (;;) { - while (*start == ' ') - start++; - if (*start == '\0') - break; - end = strchr(start, ' '); - if (end) - *end = '\0'; - - if (rsn_preauth_iface_add(hapd, start)) { - rsn_preauth_iface_deinit(hapd); - return -1; - } - - if (end) - start = end + 1; - else - break; - } - 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) -{ - 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_crypt(sta->eapol_sm, &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) { - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "RSN: Could not find " - "pre-authentication interface for " MACSTR "\n", - MAC2STR(sta->addr)); - return; - } - - ethhdr = malloc(sizeof(*ethhdr) + len); - if (ethhdr == NULL) - return; - - memcpy(ethhdr->h_dest, sta->addr, ETH_ALEN); - memcpy(ethhdr->h_source, hapd->own_addr, ETH_ALEN); - ethhdr->h_proto = htons(ETH_P_PREAUTH); - memcpy(ethhdr + 1, buf, len); - - if (l2_packet_send(piface->l2, sta->addr, ETH_P_PREAUTH, (u8 *) ethhdr, - sizeof(*ethhdr) + len) < 0) { - printf("Failed to send preauth packet using l2_packet_send\n"); - } - 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/contrib/hostapd/preauth.h b/contrib/hostapd/preauth.h deleted file mode 100644 index 5348bee9bf72..000000000000 --- a/contrib/hostapd/preauth.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * hostapd - Authenticator for IEEE 802.11i RSN pre-authentication - * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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/contrib/hostapd/radius.c b/contrib/hostapd/radius.c deleted file mode 100644 index 743f3400f1de..000000000000 --- a/contrib/hostapd/radius.c +++ /dev/null @@ -1,1228 +0,0 @@ -/* - * hostapd / RADIUS message processing - * Copyright (c) 2002-2008, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "md5.h" -#include "crypto.h" - - -struct radius_msg *radius_msg_new(u8 code, u8 identifier) -{ - struct radius_msg *msg; - - msg = os_malloc(sizeof(*msg)); - if (msg == NULL) - return NULL; - - if (radius_msg_initialize(msg, RADIUS_DEFAULT_MSG_SIZE)) { - os_free(msg); - return NULL; - } - - radius_msg_set_hdr(msg, code, identifier); - - return msg; -} - - -int radius_msg_initialize(struct radius_msg *msg, size_t init_len) -{ - if (msg == NULL || init_len < sizeof(struct radius_hdr)) - return -1; - - os_memset(msg, 0, sizeof(*msg)); - msg->buf = wpa_zalloc(init_len); - if (msg->buf == NULL) - return -1; - - msg->buf_size = init_len; - msg->hdr = (struct radius_hdr *) msg->buf; - msg->buf_used = sizeof(*msg->hdr); - - msg->attrs = - os_malloc(RADIUS_DEFAULT_ATTR_COUNT * sizeof(*msg->attrs)); - if (msg->attrs == NULL) { - os_free(msg->buf); - msg->buf = NULL; - msg->hdr = NULL; - return -1; - } - - msg->attr_size = RADIUS_DEFAULT_ATTR_COUNT; - msg->attr_used = 0; - - return 0; -} - - -void radius_msg_set_hdr(struct radius_msg *msg, u8 code, u8 identifier) -{ - msg->hdr->code = code; - msg->hdr->identifier = identifier; -} - - -void radius_msg_free(struct radius_msg *msg) -{ - if (msg->buf != NULL) { - os_free(msg->buf); - msg->buf = NULL; - msg->hdr = NULL; - } - msg->buf_size = msg->buf_used = 0; - - if (msg->attrs != NULL) { - os_free(msg->attrs); - msg->attrs = NULL; - } - msg->attr_size = msg->attr_used = 0; -} - - -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_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_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++) { - radius_msg_dump_attr(msg->attrs[i]); - } -} - - -int radius_msg_finish(struct radius_msg *msg, 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) { - printf("WARNING: Could not add " - "Message-Authenticator\n"); - return -1; - } - msg->hdr->length = htons(msg->buf_used); - hmac_md5(secret, secret_len, msg->buf, msg->buf_used, - (u8 *) (attr + 1)); - } else - msg->hdr->length = htons(msg->buf_used); - - if (msg->buf_used > 0xffff) { - printf("WARNING: too long RADIUS message (%lu)\n", - (unsigned long) msg->buf_used); - 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(msg->buf_used); - os_memcpy(msg->hdr->authenticator, req_authenticator, - sizeof(msg->hdr->authenticator)); - hmac_md5(secret, secret_len, msg->buf, msg->buf_used, - (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] = (u8 *) (msg->hdr + 1); - len[2] = msg->buf_used - sizeof(*msg->hdr); - addr[3] = secret; - len[3] = secret_len; - md5_vector(4, addr, len, msg->hdr->authenticator); - - if (msg->buf_used > 0xffff) { - printf("WARNING: too long RADIUS message (%lu)\n", - (unsigned long) msg->buf_used); - return -1; - } - return 0; -} - - -void radius_msg_finish_acct(struct radius_msg *msg, u8 *secret, - size_t secret_len) -{ - const u8 *addr[2]; - size_t len[2]; - - msg->hdr->length = htons(msg->buf_used); - os_memset(msg->hdr->authenticator, 0, MD5_MAC_LEN); - addr[0] = msg->buf; - len[0] = msg->buf_used; - addr[1] = secret; - len[1] = secret_len; - md5_vector(2, addr, len, msg->hdr->authenticator); - - if (msg->buf_used > 0xffff) { - printf("WARNING: too long RADIUS messages (%lu)\n", - (unsigned long) msg->buf_used); - } -} - - -static int radius_msg_add_attr_to_array(struct radius_msg *msg, - struct radius_attr_hdr *attr) -{ - if (msg->attr_used >= msg->attr_size) { - struct radius_attr_hdr **nattrs; - int nlen = msg->attr_size * 2; - - nattrs = os_realloc(msg->attrs, nlen * sizeof(*msg->attrs)); - if (nattrs == NULL) - return -1; - - msg->attrs = nattrs; - msg->attr_size = nlen; - } - - msg->attrs[msg->attr_used++] = attr; - - 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 = msg->buf_used + sizeof(*attr) + data_len; - - if (msg->buf_size < buf_needed) { - /* allocate more space for message buffer */ - unsigned char *nbuf; - size_t i, nlen = msg->buf_size; - int diff; - - while (nlen < buf_needed) - nlen *= 2; - nbuf = os_realloc(msg->buf, nlen); - if (nbuf == NULL) - return NULL; - diff = nbuf - msg->buf; - msg->buf = nbuf; - msg->hdr = (struct radius_hdr *) msg->buf; - /* adjust attr pointers to match with the new buffer */ - for (i = 0; i < msg->attr_used; i++) - msg->attrs[i] = (struct radius_attr_hdr *) - (((u8 *) msg->attrs[i]) + diff); - os_memset(msg->buf + msg->buf_size, 0, nlen - msg->buf_size); - msg->buf_size = nlen; - } - - attr = (struct radius_attr_hdr *) (msg->buf + msg->buf_used); - attr->type = type; - attr->length = sizeof(*attr) + data_len; - if (data_len > 0) - os_memcpy(attr + 1, data, data_len); - - msg->buf_used += sizeof(*attr) + data_len; - - if (radius_msg_add_attr_to_array(msg, attr)) - return NULL; - - return attr; -} - - -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) { - printf("Invalid RADIUS message length\n"); - return NULL; - } - - if (msg_len < len) { - printf("Ignored %lu extra bytes after RADIUS message\n", - (unsigned long) len - msg_len); - } - - msg = os_malloc(sizeof(*msg)); - if (msg == NULL) - return NULL; - - if (radius_msg_initialize(msg, msg_len)) { - os_free(msg); - return NULL; - } - - os_memcpy(msg->buf, data, msg_len); - msg->buf_size = msg->buf_used = msg_len; - - /* parse attributes */ - pos = (unsigned char *) (msg->hdr + 1); - end = msg->buf + msg->buf_used; - 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); - os_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; - - if (msg == NULL) - return NULL; - - len = 0; - for (i = 0; i < msg->attr_used; i++) { - if (msg->attrs[i]->type == RADIUS_ATTR_EAP_MESSAGE) - len += msg->attrs[i]->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++) { - if (msg->attrs[i]->type == RADIUS_ATTR_EAP_MESSAGE) { - struct radius_attr_hdr *attr = msg->attrs[i]; - 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; - size_t i; - - for (i = 0; i < msg->attr_used; i++) { - if (msg->attrs[i]->type == RADIUS_ATTR_MESSAGE_AUTHENTICATOR) { - if (attr != NULL) { - printf("Multiple Message-Authenticator " - "attributes in RADIUS message\n"); - return 1; - } - attr = msg->attrs[i]; - } - } - - 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, msg->buf, msg->buf_used, 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] = (u8 *) (msg->hdr + 1); - len[2] = msg->buf_used - sizeof(*msg->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 = src->attrs[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 = msg->attrs[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; - - 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] > 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]; - - saltbuf[0] = salt >> 8; - saltbuf[1] = 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, - 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 = wpa_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, - 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 = wpa_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; - *pos++ = salt >> 8; - *pos++ = salt; - 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; - *pos++ = salt >> 8; - *pos++ = salt; - 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, - u8 *data, size_t data_len, - 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; - size_t i, dlen; - - for (i = 0; i < msg->attr_used; i++) { - if (msg->attrs[i]->type == type) { - attr = msg->attrs[i]; - 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; - - for (i = 0; i < msg->attr_used; i++) { - if (msg->attrs[i]->type == type && - (start == NULL || (u8 *) msg->attrs[i] > start)) { - attr = msg->attrs[i]; - 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++) { - if (msg->attrs[i]->type == type && - msg->attrs[i]->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 = msg->attrs[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 = (data[1] << 16) | (data[2] << 8) | data[3]; - break; - case RADIUS_ATTR_TUNNEL_MEDIUM_TYPE: - if (attr->length != 6) - break; - tun->tag_used++; - tun->medium_type = - (data[1] << 16) | (data[2] << 8) | data[3]; - 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; -} diff --git a/contrib/hostapd/radius.h b/contrib/hostapd/radius.h deleted file mode 100644 index d4375376a94f..000000000000 --- a/contrib/hostapd/radius.h +++ /dev/null @@ -1,267 +0,0 @@ -/* - * hostapd / RADIUS message processing - * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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_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_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; -}; - - -/* RADIUS message structure for new and parsed messages */ -struct radius_msg { - unsigned char *buf; - size_t buf_size; /* total size allocated for buf */ - size_t buf_used; /* bytes used in buf */ - - struct radius_hdr *hdr; - - struct radius_attr_hdr **attrs; /* array of pointers to attributes */ - size_t attr_size; /* total size of the attribute pointer array */ - size_t attr_used; /* total number of attributes in the array */ -}; - - -/* 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_msg *radius_msg_new(u8 code, u8 identifier); -int radius_msg_initialize(struct radius_msg *msg, size_t init_len); -void radius_msg_set_hdr(struct radius_msg *msg, 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, 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, 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, - 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, - 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, - u8 *data, size_t data_len, - 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); - -#endif /* RADIUS_H */ diff --git a/contrib/hostapd/radius_client.c b/contrib/hostapd/radius_client.c deleted file mode 100644 index 81cd9c58b16b..000000000000 --- a/contrib/hostapd/radius_client.c +++ /dev/null @@ -1,1219 +0,0 @@ -/* - * hostapd / RADIUS client - * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "hostapd.h" -#include "radius.h" -#include "radius_client.h" -#include "eloop.h" - -/* Defaults for RADIUS retransmit values (exponential backoff) */ -#define RADIUS_CLIENT_FIRST_WAIT 3 /* seconds */ -#define RADIUS_CLIENT_MAX_WAIT 120 /* seconds */ -#define RADIUS_CLIENT_MAX_RETRIES 10 /* maximum number of retransmit attempts - * before entry is removed from retransmit - * list */ -#define RADIUS_CLIENT_MAX_ENTRIES 30 /* maximum number of entries in retransmit - * list (oldest will be removed, if this - * limit is exceeded) */ -#define RADIUS_CLIENT_NUM_FAILOVER 4 /* try to change RADIUS server after this - * many failed retry attempts */ - - -struct radius_rx_handler { - RadiusRxResult (*handler)(struct radius_msg *msg, - struct radius_msg *req, - u8 *shared_secret, size_t shared_secret_len, - void *data); - void *data; -}; - - -/* RADIUS message retransmit list */ -struct radius_msg_list { - u8 addr[ETH_ALEN]; /* STA/client address; used to find RADIUS messages - * for the same STA. */ - struct radius_msg *msg; - RadiusType msg_type; - os_time_t first_try; - os_time_t next_try; - int attempts; - int next_wait; - struct os_time last_attempt; - - u8 *shared_secret; - size_t shared_secret_len; - - /* TODO: server config with failover to backup server(s) */ - - struct radius_msg_list *next; -}; - - -struct radius_client_data { - void *ctx; - struct hostapd_radius_servers *conf; - - int auth_serv_sock; /* socket for authentication RADIUS messages */ - int acct_serv_sock; /* socket for accounting RADIUS messages */ - int auth_serv_sock6; - int acct_serv_sock6; - int auth_sock; /* currently used socket */ - int acct_sock; /* currently used socket */ - - struct radius_rx_handler *auth_handlers; - size_t num_auth_handlers; - struct radius_rx_handler *acct_handlers; - size_t num_acct_handlers; - - struct radius_msg_list *msgs; - size_t num_msgs; - - 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->msg); - os_free(req); -} - - -int radius_client_register(struct radius_client_data *radius, - RadiusType msg_type, - RadiusRxResult (*handler)(struct radius_msg *msg, - struct radius_msg *req, - 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; - - 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)", - entry->msg->hdr->identifier); - - os_get_time(&entry->last_attempt); - if (send(s, entry->msg->buf, entry->msg->buf_used, 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, 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); - os_free(msg); - return; - } - - entry = wpa_zalloc(sizeof(*entry)); - if (entry == NULL) { - printf("Failed to add RADIUS packet into retransmit list\n"); - radius_msg_free(msg); - os_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; - } -} - - -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; - u8 *shared_secret; - size_t shared_secret_len; - char *name; - int s, res; - - 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); - - res = send(s, msg->buf, msg->buf_used, 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_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; - } - - hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_DEBUG, "Received RADIUS message"); - if (conf->msg_dumps) - radius_msg_dump(msg); - - switch (msg->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)) && - req->msg->hdr->identifier == msg->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, msg->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); - os_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, msg->hdr->code, msg->hdr->identifier, - invalid_authenticator ? " [INVALID AUTHENTICATOR]" : - ""); - radius_client_msg_free(req); - - fail: - radius_msg_free(msg); - os_free(msg); -} - - -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 (entry->msg->hdr->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; -} - - -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); -} - - -void radius_client_update_acct_msgs(struct radius_client_data *radius, - 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; -#ifdef CONFIG_IPV6 - struct sockaddr_in6 serv6; -#endif /* CONFIG_IPV6 */ - struct sockaddr *addr; - socklen_t addrlen; - char abuf[50]; - int sel_sock; - struct radius_msg_list *entry; - - 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 (connect(sel_sock, addr, addrlen) < 0) { - perror("connect[radius]"); - return -1; - } - - 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_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 - 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 - 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; -} - - -struct radius_client_data * -radius_client_init(void *ctx, struct hostapd_radius_servers *conf) -{ - struct radius_client_data *radius; - - radius = wpa_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; -} - - -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); - - 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); -} - - -void radius_client_flush_auth(struct radius_client_data *radius, 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); -} - - -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; -} - - -static int radius_servers_diff(struct hostapd_radius_server *nserv, - struct hostapd_radius_server *oserv, - int num) -{ - int i; - - for (i = 0; i < num; i++) { - if (hostapd_ip_diff(&nserv[i].addr, &oserv[i].addr) || - nserv[i].port != oserv[i].port || - nserv[i].shared_secret_len != oserv[i].shared_secret_len || - memcmp(nserv[i].shared_secret, oserv[i].shared_secret, - nserv[i].shared_secret_len) != 0) - return 1; - } - - return 0; -} - - -struct radius_client_data * -radius_client_reconfig(struct radius_client_data *old, void *ctx, - struct hostapd_radius_servers *oldconf, - struct hostapd_radius_servers *newconf) -{ - radius_client_flush(old, 0); - - if (newconf->retry_primary_interval != - oldconf->retry_primary_interval || - newconf->num_auth_servers != oldconf->num_auth_servers || - newconf->num_acct_servers != oldconf->num_acct_servers || - radius_servers_diff(newconf->auth_servers, oldconf->auth_servers, - newconf->num_auth_servers) || - radius_servers_diff(newconf->acct_servers, oldconf->acct_servers, - newconf->num_acct_servers)) { - hostapd_logger(ctx, NULL, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_DEBUG, - "Reconfiguring RADIUS client"); - radius_client_deinit(old); - return radius_client_init(ctx, newconf); - } - - return old; -} diff --git a/contrib/hostapd/radius_client.h b/contrib/hostapd/radius_client.h deleted file mode 100644 index df1ba1f9b209..000000000000 --- a/contrib/hostapd/radius_client.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * hostapd / RADIUS client - * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "config_types.h" - -struct radius_msg; - -struct hostapd_radius_server { - /* MIB prefix for shared variables: - * @ = radiusAuth or radiusAcc depending on the type of the server */ - struct hostapd_ip_addr addr; /* @ServerAddress */ - int port; /* @ClientServerPortNumber */ - u8 *shared_secret; - size_t shared_secret_len; - - /* Dynamic (not from configuration file) MIB data */ - int index; /* @ServerIndex */ - int round_trip_time; /* @ClientRoundTripTime; in hundredths of a - * second */ - u32 requests; /* @Client{Access,}Requests */ - u32 retransmissions; /* @Client{Access,}Retransmissions */ - u32 access_accepts; /* radiusAuthClientAccessAccepts */ - u32 access_rejects; /* radiusAuthClientAccessRejects */ - u32 access_challenges; /* radiusAuthClientAccessChallenges */ - u32 responses; /* radiusAccClientResponses */ - u32 malformed_responses; /* @ClientMalformed{Access,}Responses */ - u32 bad_authenticators; /* @ClientBadAuthenticators */ - u32 timeouts; /* @ClientTimeouts */ - u32 unknown_types; /* @ClientUnknownTypes */ - u32 packets_dropped; /* @ClientPacketsDropped */ - /* @ClientPendingRequests: length of hapd->radius->msgs for matching - * msg_type */ -}; - -struct hostapd_radius_servers { - /* RADIUS Authentication and Accounting servers in priority order */ - struct hostapd_radius_server *auth_servers, *auth_server; - int num_auth_servers; - struct hostapd_radius_server *acct_servers, *acct_server; - int num_acct_servers; - - int retry_primary_interval; - int acct_interim_interval; - - int msg_dumps; -}; - - -typedef enum { - RADIUS_AUTH, - RADIUS_ACCT, - RADIUS_ACCT_INTERIM /* used only with radius_client_send(); just like - * RADIUS_ACCT, but removes any pending interim - * RADIUS Accounting packages for the same STA - * before sending the new interim update */ -} RadiusType; - -typedef enum { - RADIUS_RX_PROCESSED, - RADIUS_RX_QUEUED, - RADIUS_RX_UNKNOWN, - 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, - 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, u8 *addr); -int radius_client_get_mib(struct radius_client_data *radius, char *buf, - size_t buflen); -struct radius_client_data * -radius_client_reconfig(struct radius_client_data *old, void *ctx, - struct hostapd_radius_servers *oldconf, - struct hostapd_radius_servers *newconf); - -#endif /* RADIUS_CLIENT_H */ diff --git a/contrib/hostapd/radius_server.c b/contrib/hostapd/radius_server.c deleted file mode 100644 index 409d537f42ab..000000000000 --- a/contrib/hostapd/radius_server.c +++ /dev/null @@ -1,1365 +0,0 @@ -/* - * hostapd / RADIUS authentication server - * Copyright (c) 2005-2008, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 <net/if.h> - -#include "common.h" -#include "radius.h" -#include "eloop.h" -#include "config.h" -#include "eap.h" -#include "radius_server.h" - -#define RADIUS_SESSION_TIMEOUT 60 -#define RADIUS_MAX_SESSION 100 -#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 { - 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 { - struct radius_session *next; - struct radius_client *client; - struct radius_server_data *server; - unsigned int sess_id; - struct eap_sm *eap; - u8 *eapKeyData, *eapReqData; - size_t eapKeyDataLen, eapReqDataLen; - Boolean eapSuccess, eapRestart, eapFail, eapResp, eapReq, eapNoReq; - Boolean portEnabled, eapTimeout; - - 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 { - 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 { - int auth_sock; - struct radius_client *clients; - unsigned int next_sess_id; - void *hostapd_conf; - int num_sess; - void *eap_sim_db_priv; - void *ssl_ctx; - int ipv6; - struct os_time start_time; - struct radius_server_counters counters; -}; - - -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 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); - free(sess->eapKeyData); - free(sess->eapReqData); - eap_sm_deinit(sess->eap); - if (sess->last_msg) { - radius_msg_free(sess->last_msg); - free(sess->last_msg); - } - free(sess->last_from_addr); - if (sess->last_reply) { - radius_msg_free(sess->last_reply); - free(sess->last_reply); - } - free(sess); - data->num_sess--; -} - - -static void radius_server_session_remove_timeout(void *eloop_ctx, - void *timeout_ctx); - -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 = wpa_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; - const struct hostapd_eap_user *eap_user; - int res; - struct radius_session *sess; - struct eap_config eap_conf; - - RADIUS_DEBUG("Creating a new session"); - - user = 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"); - free(user); - return NULL; - } - user_len = res; - RADIUS_DUMP_ASCII("User-Name", user, user_len); - - eap_user = hostapd_get_eap_user(data->hostapd_conf, user, user_len, 0); - free(user); - - if (eap_user) { - 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; - } - - memset(&eap_conf, 0, sizeof(eap_conf)); - eap_conf.ssl_ctx = data->ssl_ctx; - eap_conf.eap_sim_db_priv = data->eap_sim_db_priv; - eap_conf.backend_auth = TRUE; - sess->eap = eap_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->eapRestart = TRUE; - sess->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; - - if (sess->eapFail) { - code = RADIUS_CODE_ACCESS_REJECT; - } else if (sess->eapSuccess) { - code = RADIUS_CODE_ACCESS_ACCEPT; - } else { - code = RADIUS_CODE_ACCESS_CHALLENGE; - } - - msg = radius_msg_new(code, request->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->eapReqData && - !radius_msg_add_eap(msg, sess->eapReqData, sess->eapReqDataLen)) { - RADIUS_DEBUG("Failed to add EAP-Message attribute"); - } - - if (code == RADIUS_CODE_ACCESS_ACCEPT && sess->eapKeyData) { - int len; - if (sess->eapKeyDataLen > 64) { - len = 32; - } else { - len = sess->eapKeyDataLen / 2; - } - if (!radius_msg_add_mppe_keys(msg, request->hdr->authenticator, - (u8 *) client->shared_secret, - client->shared_secret_len, - sess->eapKeyData + len, len, - sess->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); - os_free(msg); - return NULL; - } - - if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret, - client->shared_secret_len, - request->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; - - RADIUS_DEBUG("Reject invalid request from %s:%d", - from_addr, from_port); - - msg = radius_msg_new(RADIUS_CODE_ACCESS_REJECT, - request->hdr->identifier); - if (msg == NULL) { - return -1; - } - - memset(&eapfail, 0, sizeof(eapfail)); - eapfail.code = EAP_CODE_FAILURE; - eapfail.identifier = 0; - eapfail.length = htons(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); - os_free(msg); - return -1; - } - - if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret, - client->shared_secret_len, - request->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++; - if (sendto(data->auth_sock, msg->buf, msg->buf_used, 0, - (struct sockaddr *) from, sizeof(*from)) < 0) { - perror("sendto[RADIUS SRV]"); - ret = -1; - } - - radius_msg_free(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], resp_id; - unsigned int state; - struct radius_session *sess; - struct radius_msg *reply; - struct eap_hdr *hdr; - - 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 = (statebuf[0] << 24) | (statebuf[1] << 16) | - (statebuf[2] << 8) | statebuf[3]; - 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 == msg->hdr->identifier && - os_memcmp(sess->last_authenticator, msg->hdr->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) { - res = sendto(data->auth_sock, sess->last_reply->buf, - sess->last_reply->buf_used, 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); - if (eap_len >= sizeof(*hdr)) { - hdr = (struct eap_hdr *) eap; - resp_id = hdr->identifier; - } else { - resp_id = 0; - } - - /* 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? */ - - eap_set_eapRespData(sess->eap, eap, eap_len); - free(eap); - eap = NULL; - sess->eapResp = TRUE; - eap_sm_step(sess->eap); - - if (sess->eapReqData) { - RADIUS_DUMP("EAP data from the state machine", - sess->eapReqData, sess->eapReqDataLen); - } else if (sess->eapFail) { - RADIUS_DEBUG("No EAP data from the state machine, but eapFail " - "set - generate EAP-Failure"); - hdr = wpa_zalloc(sizeof(*hdr)); - if (hdr) { - hdr->identifier = resp_id; - hdr->length = htons(sizeof(*hdr)); - sess->eapReqData = (u8 *) hdr; - sess->eapReqDataLen = sizeof(*hdr); - } - } else if (eap_sm_method_pending(sess->eap)) { - if (sess->last_msg) { - radius_msg_free(sess->last_msg); - free(sess->last_msg); - } - sess->last_msg = msg; - sess->last_from_port = from_port; - free(sess->last_from_addr); - sess->last_from_addr = strdup(from_addr); - sess->last_fromlen = fromlen; - 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; - } - - reply = radius_server_encapsulate_eap(data, client, sess, msg); - - free(sess->eapReqData); - sess->eapReqData = NULL; - sess->eapReqDataLen = 0; - - if (reply) { - RADIUS_DEBUG("Reply to %s:%d", from_addr, from_port); - if (wpa_debug_level <= MSG_MSGDUMP) { - radius_msg_dump(reply); - } - - switch (reply->hdr->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; - } - res = sendto(data->auth_sock, reply->buf, reply->buf_used, 0, - (struct sockaddr *) from, fromlen); - if (res < 0) { - perror("sendto[RADIUS SRV]"); - } - if (sess->last_reply) { - radius_msg_free(sess->last_reply); - free(sess->last_reply); - } - sess->last_reply = reply; - sess->last_from_port = from_port; - sess->last_identifier = msg->hdr->identifier; - os_memcpy(sess->last_authenticator, msg->hdr->authenticator, - 16); - } else { - data->counters.packets_dropped++; - client->counters.packets_dropped++; - } - - if (sess->eapSuccess || sess->eapFail) { - 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; - struct sockaddr_storage from; - socklen_t fromlen; - int len; - struct radius_client *client = NULL; - struct radius_msg *msg = NULL; - char abuf[50]; - int from_port = 0; - - buf = 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, &fromlen); - if (len < 0) { - perror("recvfrom[radius_server]"); - goto fail; - } - -#ifdef CONFIG_IPV6 - if (data->ipv6) { - struct sockaddr_in6 *from6 = (struct sockaddr_in6 *) &from; - if (inet_ntop(AF_INET6, &from6->sin6_addr, abuf, sizeof(abuf)) - == NULL) - abuf[0] = '\0'; - from_port = ntohs(from6->sin6_port); - RADIUS_DEBUG("Received %d bytes from %s:%d", - len, abuf, from_port); - - client = radius_server_get_client(data, - (struct in_addr *) - &from6->sin6_addr, 1); - } -#endif /* CONFIG_IPV6 */ - - if (!data->ipv6) { - struct sockaddr_in *from4 = (struct sockaddr_in *) &from; - snprintf(abuf, sizeof(abuf), "%s", inet_ntoa(from4->sin_addr)); - from_port = ntohs(from4->sin_port); - RADIUS_DEBUG("Received %d bytes from %s:%d", - len, abuf, from_port); - - client = radius_server_get_client(data, &from4->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; - } - - free(buf); - buf = NULL; - - if (wpa_debug_level <= MSG_MSGDUMP) { - radius_msg_dump(msg); - } - - if (msg->hdr->code != RADIUS_CODE_ACCESS_REQUEST) { - RADIUS_DEBUG("Unexpected RADIUS code %d", msg->hdr->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: - if (msg) { - radius_msg_free(msg); - free(msg); - } - free(buf); -} - - -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; - } - - 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; - } - - memset(&addr, 0, sizeof(addr)); - addr.sin6_family = AF_INET6; - 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); - free(prev->shared_secret); - 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 = 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); - memset(addr6.s6_addr, 0, 10); - addr6.s6_addr[10] = 0xff; - addr6.s6_addr[11] = 0xff; - 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 = wpa_zalloc(sizeof(*entry)); - if (entry == NULL) { - failed = 1; - break; - } - entry->shared_secret = strdup(pos); - if (entry->shared_secret == NULL) { - failed = 1; - free(entry); - break; - } - entry->shared_secret_len = 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; - - memcpy(entry->addr6.s6_addr, addr6.s6_addr, 16); - 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; - } - - free(buf); - fclose(f); - - return clients; -} - - -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 = wpa_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - - os_get_time(&data->start_time); - data->hostapd_conf = conf->hostapd_conf; - data->eap_sim_db_priv = conf->eap_sim_db_priv; - data->ssl_ctx = conf->ssl_ctx; - data->ipv6 = conf->ipv6; - - 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; -} - - -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); - - free(data); -} - - -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 = 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 = 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) { - snprintf(abuf, sizeof(abuf), "%s", - inet_ntoa(cli->addr)); - snprintf(mbuf, sizeof(mbuf), "%s", - inet_ntoa(cli->mask)); - } - - ret = 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 Boolean radius_server_get_bool(void *ctx, enum eapol_bool_var variable) -{ - struct radius_session *sess = ctx; - if (sess == NULL) - return FALSE; - switch (variable) { - case EAPOL_eapSuccess: - return sess->eapSuccess; - case EAPOL_eapRestart: - return sess->eapRestart; - case EAPOL_eapFail: - return sess->eapFail; - case EAPOL_eapResp: - return sess->eapResp; - case EAPOL_eapReq: - return sess->eapReq; - case EAPOL_eapNoReq: - return sess->eapNoReq; - case EAPOL_portEnabled: - return sess->portEnabled; - case EAPOL_eapTimeout: - return sess->eapTimeout; - } - return FALSE; -} - - -static void radius_server_set_bool(void *ctx, enum eapol_bool_var variable, - Boolean value) -{ - struct radius_session *sess = ctx; - if (sess == NULL) - return; - switch (variable) { - case EAPOL_eapSuccess: - sess->eapSuccess = value; - break; - case EAPOL_eapRestart: - sess->eapRestart = value; - break; - case EAPOL_eapFail: - sess->eapFail = value; - break; - case EAPOL_eapResp: - sess->eapResp = value; - break; - case EAPOL_eapReq: - sess->eapReq = value; - break; - case EAPOL_eapNoReq: - sess->eapNoReq = value; - break; - case EAPOL_portEnabled: - sess->portEnabled = value; - break; - case EAPOL_eapTimeout: - sess->eapTimeout = value; - break; - } -} - - -static void radius_server_set_eapReqData(void *ctx, const u8 *eapReqData, - size_t eapReqDataLen) -{ - struct radius_session *sess = ctx; - if (sess == NULL) - return; - - free(sess->eapReqData); - sess->eapReqData = malloc(eapReqDataLen); - if (sess->eapReqData) { - memcpy(sess->eapReqData, eapReqData, eapReqDataLen); - sess->eapReqDataLen = eapReqDataLen; - } else { - sess->eapReqDataLen = 0; - } -} - - -static void radius_server_set_eapKeyData(void *ctx, const u8 *eapKeyData, - size_t eapKeyDataLen) -{ - struct radius_session *sess = ctx; - - if (sess == NULL) - return; - - free(sess->eapKeyData); - if (eapKeyData) { - sess->eapKeyData = malloc(eapKeyDataLen); - if (sess->eapKeyData) { - memcpy(sess->eapKeyData, eapKeyData, eapKeyDataLen); - sess->eapKeyDataLen = eapKeyDataLen; - } else { - sess->eapKeyDataLen = 0; - } - } else { - sess->eapKeyData = NULL; - sess->eapKeyDataLen = 0; - } -} - - -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; - const struct hostapd_eap_user *eap_user; - int i, count; - - eap_user = hostapd_get_eap_user(sess->server->hostapd_conf, identity, - identity_len, phase2); - if (eap_user == NULL) - return -1; - - 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 = malloc(eap_user->password_len); - if (user->password == NULL) - return -1; - 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; - - return 0; -} - - -static struct eapol_callbacks radius_server_eapol_cb = -{ - .get_bool = radius_server_get_bool, - .set_bool = radius_server_set_bool, - .set_eapReqData = radius_server_set_eapReqData, - .set_eapKeyData = radius_server_set_eapKeyData, - .get_eap_user = radius_server_get_eap_user, -}; - - -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); - free(msg); -} diff --git a/contrib/hostapd/radius_server.h b/contrib/hostapd/radius_server.h deleted file mode 100644 index 9c9315e60706..000000000000 --- a/contrib/hostapd/radius_server.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * hostapd / RADIUS authentication server - * Copyright (c) 2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 radius_server_conf { - int auth_port; - char *client_file; - void *hostapd_conf; - void *eap_sim_db_priv; - void *ssl_ctx; - int ipv6; -}; - - -#ifdef RADIUS_SERVER - -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); - -#else /* RADIUS_SERVER */ - -static inline struct radius_server_data * -radius_server_init(struct radius_server_conf *conf) -{ - return NULL; -} - -static inline void radius_server_deinit(struct radius_server_data *data) -{ -} - -static inline int radius_server_get_mib(struct radius_server_data *data, - char *buf, size_t buflen) -{ - return 0; -} - -static inline void -radius_server_eap_pending_cb(struct radius_server_data *data, void *ctx) -{ -} - -#endif /* RADIUS_SERVER */ - -#endif /* RADIUS_SERVER_H */ diff --git a/contrib/hostapd/rc4.c b/contrib/hostapd/rc4.c deleted file mode 100644 index 8480cc55cea6..000000000000 --- a/contrib/hostapd/rc4.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * RC4 stream cipher - * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "rc4.h" - -#define S_SWAP(a,b) do { u8 t = S[a]; S[a] = S[b]; S[b] = t; } while(0) - -/** - * rc4 - 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 - * - * 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. - */ -void 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]; - } -} - - -/** - * rc4 - XOR RC4 stream to given data - * @buf: data to be XOR'ed with RC4 stream - * @len: buf length - * @key: RC4 key - * @key_len: RC4 key length - * - * Generate RC4 pseudo random stream for the given key and XOR this with the - * data buffer to perform RC4 encryption/decryption. - */ -void rc4(u8 *buf, size_t len, const u8 *key, size_t key_len) -{ - rc4_skip(key, key_len, 0, buf, len); -} diff --git a/contrib/hostapd/rc4.h b/contrib/hostapd/rc4.h deleted file mode 100644 index 01f13833ddc8..000000000000 --- a/contrib/hostapd/rc4.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * RC4 stream cipher - * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 RC4_H -#define RC4_H - -void rc4_skip(const u8 *key, size_t keylen, size_t skip, - u8 *data, size_t data_len); -void rc4(u8 *buf, size_t len, const u8 *key, size_t key_len); - -#endif /* RC4_H */ diff --git a/contrib/hostapd/reconfig.c b/contrib/hostapd/reconfig.c deleted file mode 100644 index a0d61569812b..000000000000 --- a/contrib/hostapd/reconfig.c +++ /dev/null @@ -1,714 +0,0 @@ -/* - * hostapd / Configuration reloading - * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi> - * 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. - */ - -#include "includes.h" - -#include "hostapd.h" -#include "beacon.h" -#include "hw_features.h" -#include "driver.h" -#include "sta_info.h" -#include "radius_client.h" -#include "ieee802_11.h" -#include "iapp.h" -#include "ap_list.h" -#include "wpa.h" -#include "vlan_init.h" -#include "ieee802_11_auth.h" -#include "ieee802_1x.h" -#include "accounting.h" -#include "eloop.h" - - -/** - * struct hostapd_config_change - Configuration change information - * This is for two purposes: - * - Storing configuration information in the hostapd_iface during - * the asynchronous parts of reconfiguration. - * - Passing configuration information for per-station reconfiguration. - */ -struct hostapd_config_change { - struct hostapd_data *hapd; - struct hostapd_config *newconf, *oldconf; - struct hostapd_bss_config *newbss, *oldbss; - int mac_acl_changed; - int num_sta_remove; /* number of STAs that need to be removed */ - int beacon_changed; - struct hostapd_iface *hapd_iface; - struct hostapd_data **new_hapd, **old_hapd; - int num_old_hapd; -}; - - -static int hostapd_config_reload_sta(struct hostapd_data *hapd, - struct sta_info *sta, void *data) -{ - struct hostapd_config_change *change = data; - struct hostapd_bss_config *newbss, *oldbss; - int deauth = 0; - u8 reason = WLAN_REASON_PREV_AUTH_NOT_VALID; - - newbss = change->newbss; - oldbss = change->oldbss; - hapd = change->hapd; - - if (sta->ssid == &oldbss->ssid) { - sta->ssid = &newbss->ssid; - - if (newbss->ssid.ssid_len != oldbss->ssid.ssid_len || - memcmp(newbss->ssid.ssid, oldbss->ssid.ssid, - newbss->ssid.ssid_len) != 0) { - /* main SSID was changed - kick STA out */ - deauth++; - } - } - sta->ssid_probe = sta->ssid; - - /* - * If MAC ACL configuration has changed, deauthenticate stations that - * have been removed from accepted list or have been added to denied - * list. If external RADIUS server is used for ACL, all stations are - * deauthenticated and they will need to authenticate again. This - * limits sudden load on the RADIUS server since the verification will - * be done over the time needed for the STAs to reauthenticate - * themselves. - */ - if (change->mac_acl_changed && - (newbss->macaddr_acl == USE_EXTERNAL_RADIUS_AUTH || - !hostapd_allowed_address(hapd, sta->addr, NULL, 0, NULL, NULL, - NULL))) - deauth++; - - if (newbss->ieee802_1x != oldbss->ieee802_1x && - sta->ssid == &hapd->conf->ssid) - deauth++; - - if (newbss->wpa != oldbss->wpa) - deauth++; - - if (!newbss->wme_enabled && (sta->flags & WLAN_STA_WME)) - deauth++; - - if (newbss->auth_algs != oldbss->auth_algs && - ((sta->auth_alg == WLAN_AUTH_OPEN && - !(newbss->auth_algs & HOSTAPD_AUTH_OPEN)) || - (sta->auth_alg == WLAN_AUTH_SHARED_KEY && - !(newbss->auth_algs & HOSTAPD_AUTH_SHARED_KEY)))) - deauth++; - - if (change->num_sta_remove > 0) { - deauth++; - reason = WLAN_REASON_DISASSOC_AP_BUSY; - } - - if (deauth) { - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "STA " MACSTR - " deauthenticated during config reloading " - "(reason=%d)\n", MAC2STR(sta->addr), reason); - ieee802_11_send_deauth(hapd, sta->addr, reason); - ap_sta_deauthenticate(hapd, sta, reason); - change->num_sta_remove--; - } - - return 0; -} - - -static void hostapd_reconfig_tx_queue_params(struct hostapd_data *hapd, - struct hostapd_config *newconf, - struct hostapd_config *oldconf) -{ - int i; - struct hostapd_tx_queue_params *o, *n; - - for (i = 0; i < NUM_TX_QUEUES; i++) { - o = &oldconf->tx_queue[i]; - n = &newconf->tx_queue[i]; - - if (!n->configured) - continue; - - if ((n->aifs != o->aifs || n->cwmin != o->cwmin || - n->cwmax != o->cwmax || n->burst != o->burst) && - hostapd_set_tx_queue_params(hapd, i, n->aifs, n->cwmin, - n->cwmax, n->burst)) - printf("Failed to set TX queue parameters for queue %d" - ".\n", i); - } -} - - -static int hostapd_reconfig_wme(struct hostapd_data *hapd, - struct hostapd_config *newconf, - struct hostapd_config *oldconf) -{ - int beacon_changed = 0; - size_t i; - struct hostapd_wme_ac_params *o, *n; - - for (i = 0; i < sizeof(newconf->wme_ac_params) / - sizeof(newconf->wme_ac_params[0]); i++) { - o = &oldconf->wme_ac_params[i]; - n = &newconf->wme_ac_params[i]; - if (n->cwmin != o->cwmin || - n->cwmax != o->cwmax || - n->aifs != o->aifs || - n->txopLimit != o->txopLimit || - n->admission_control_mandatory != - o->admission_control_mandatory) { - beacon_changed++; - hapd->parameter_set_count++; - } - } - - return beacon_changed; -} - - -static int rate_array_diff(int *a1, int *a2) -{ - int i; - - if (a1 == NULL && a2 == NULL) - return 0; - if (a1 == NULL || a2 == NULL) - return 1; - - i = 0; - for (;;) { - if (a1[i] != a2[i]) - return 1; - if (a1[i] == -1) - break; - i++; - } - - return 0; -} - - -static int hostapd_acl_diff(struct hostapd_bss_config *a, - struct hostapd_bss_config *b) -{ - int i; - - if (a->macaddr_acl != b->macaddr_acl || - a->num_accept_mac != b->num_accept_mac || - a->num_deny_mac != b->num_deny_mac) - return 1; - - for (i = 0; i < a->num_accept_mac; i++) { - if (memcmp(a->accept_mac[i], b->accept_mac[i], ETH_ALEN) != 0) - return 1; - } - - for (i = 0; i < a->num_deny_mac; i++) { - if (memcmp(a->deny_mac[i], b->deny_mac[i], ETH_ALEN) != 0) - return 1; - } - - return 0; -} - - -/** - * reload_iface2 - Part 2 of reload_iface - * @hapd_iface: Pointer to hostapd interface data. - */ -static void reload_iface2(struct hostapd_iface *hapd_iface) -{ - struct hostapd_data *hapd = hapd_iface->bss[0]; - struct hostapd_config *newconf = hapd_iface->change->newconf; - struct hostapd_config *oldconf = hapd_iface->change->oldconf; - int beacon_changed = hapd_iface->change->beacon_changed; - hostapd_iface_cb cb = hapd_iface->reload_iface_cb; - - if (newconf->preamble != oldconf->preamble) { - if (hostapd_set_preamble(hapd, hapd->iconf->preamble)) - printf("Could not set preamble for kernel driver\n"); - beacon_changed++; - } - - if (newconf->beacon_int != oldconf->beacon_int) { - /* Need to change beacon interval if it has changed or if - * auto channel selection was used. */ - if (hostapd_set_beacon_int(hapd, newconf->beacon_int)) - printf("Could not set beacon interval for kernel " - "driver\n"); - if (newconf->beacon_int != oldconf->beacon_int) - beacon_changed++; - } - - if (newconf->cts_protection_type != oldconf->cts_protection_type) - beacon_changed++; - - if (newconf->rts_threshold > -1 && - newconf->rts_threshold != oldconf->rts_threshold && - hostapd_set_rts(hapd, newconf->rts_threshold)) - printf("Could not set RTS threshold for kernel driver\n"); - - if (newconf->fragm_threshold > -1 && - newconf->fragm_threshold != oldconf->fragm_threshold && - hostapd_set_frag(hapd, newconf->fragm_threshold)) - printf("Could not set fragmentation threshold for kernel " - "driver\n"); - - hostapd_reconfig_tx_queue_params(hapd, newconf, oldconf); - - if (hostapd_reconfig_wme(hapd, newconf, oldconf) > 0) - beacon_changed++; - - ap_list_reconfig(hapd_iface, oldconf); - - hapd_iface->change->beacon_changed = beacon_changed; - - hapd_iface->reload_iface_cb = NULL; - cb(hapd_iface, 0); -} - - -/** - * reload_iface2_handler - Handler that calls reload_face2 - * @eloop_data: Stores the struct hostapd_iface for the interface. - * @user_ctx: Unused. - */ -static void reload_iface2_handler(void *eloop_data, void *user_ctx) -{ - struct hostapd_iface *hapd_iface = eloop_data; - - reload_iface2(hapd_iface); -} - - -/** - * reload_hw_mode_done - Callback for after the HW mode is setup - * @hapd_iface: Pointer to interface data. - * @status: Status of the HW mode setup. - */ -static void reload_hw_mode_done(struct hostapd_iface *hapd_iface, int status) -{ - struct hostapd_data *hapd = hapd_iface->bss[0]; - struct hostapd_config_change *change = hapd_iface->change; - struct hostapd_config *newconf = change->newconf; - hostapd_iface_cb cb; - int freq; - - if (status) { - printf("Failed to select hw_mode.\n"); - - cb = hapd_iface->reload_iface_cb; - hapd_iface->reload_iface_cb = NULL; - cb(hapd_iface, -1); - - return; - } - - freq = hostapd_hw_get_freq(hapd, newconf->channel); - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "Mode: %s Channel: %d Frequency: %d MHz\n", - hostapd_hw_mode_txt(newconf->hw_mode), - newconf->channel, freq); - - if (hostapd_set_freq(hapd, newconf->hw_mode, freq)) { - printf("Could not set channel %d (%d MHz) for kernel " - "driver\n", newconf->channel, freq); - } - - change->beacon_changed++; - - reload_iface2(hapd_iface); -} - - -/** - * hostapd_config_reload_iface_start - Start interface reload - * @hapd_iface: Pointer to interface data. - * @cb: The function to callback when done. - * Returns: 0 if it starts successfully; cb will be called when done. - * -1 on failure; cb will not be called. - */ -static int hostapd_config_reload_iface_start(struct hostapd_iface *hapd_iface, - hostapd_iface_cb cb) -{ - struct hostapd_config_change *change = hapd_iface->change; - struct hostapd_config *newconf = change->newconf; - struct hostapd_config *oldconf = change->oldconf; - struct hostapd_data *hapd = hapd_iface->bss[0]; - - if (hapd_iface->reload_iface_cb) { - wpa_printf(MSG_DEBUG, - "%s: Interface reload already in progress.", - hapd_iface->bss[0]->conf->iface); - return -1; - } - - hapd_iface->reload_iface_cb = cb; - - if (newconf->bridge_packets != oldconf->bridge_packets && - hapd->iconf->bridge_packets != INTERNAL_BRIDGE_DO_NOT_CONTROL && - hostapd_set_internal_bridge(hapd, hapd->iconf->bridge_packets)) - printf("Failed to set bridge_packets for kernel driver\n"); - - if (newconf->channel != oldconf->channel || - newconf->hw_mode != oldconf->hw_mode || - rate_array_diff(newconf->supported_rates, - oldconf->supported_rates) || - rate_array_diff(newconf->basic_rates, oldconf->basic_rates)) { - hostapd_free_stas(hapd); - - if (hostapd_get_hw_features(hapd_iface)) { - printf("Could not read HW feature info from the kernel" - " driver.\n"); - hapd_iface->reload_iface_cb = NULL; - return -1; - } - - if (hostapd_select_hw_mode_start(hapd_iface, - reload_hw_mode_done)) { - printf("Failed to start select hw_mode.\n"); - hapd_iface->reload_iface_cb = NULL; - return -1; - } - - return 0; - } - - eloop_register_timeout(0, 0, reload_iface2_handler, hapd_iface, NULL); - return 0; -} - - -static void hostapd_reconfig_bss(struct hostapd_data *hapd, - struct hostapd_bss_config *newbss, - struct hostapd_bss_config *oldbss, - struct hostapd_config *oldconf, - int beacon_changed) -{ - struct hostapd_config_change change; - int encr_changed = 0; - struct radius_client_data *old_radius; - - radius_client_flush(hapd->radius, 0); - - if (hostapd_set_dtim_period(hapd, newbss->dtim_period)) - printf("Could not set DTIM period for kernel driver\n"); - - if (newbss->ssid.ssid_len != oldbss->ssid.ssid_len || - memcmp(newbss->ssid.ssid, oldbss->ssid.ssid, - newbss->ssid.ssid_len) != 0) { - if (hostapd_set_ssid(hapd, (u8 *) newbss->ssid.ssid, - newbss->ssid.ssid_len)) - printf("Could not set SSID for kernel driver\n"); - beacon_changed++; - } - - if (newbss->ignore_broadcast_ssid != oldbss->ignore_broadcast_ssid) - beacon_changed++; - - if (hostapd_wep_key_cmp(&newbss->ssid.wep, &oldbss->ssid.wep)) { - encr_changed++; - beacon_changed++; - } - - vlan_reconfig(hapd, oldconf, oldbss); - - if (beacon_changed) { - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Updating beacon frame " - "information\n"); - ieee802_11_set_beacon(hapd); - } - - change.hapd = hapd; - change.oldconf = oldconf; - change.newconf = hapd->iconf; - change.oldbss = oldbss; - change.newbss = newbss; - change.mac_acl_changed = hostapd_acl_diff(newbss, oldbss); - if (newbss->max_num_sta != oldbss->max_num_sta && - newbss->max_num_sta < hapd->num_sta) { - change.num_sta_remove = hapd->num_sta - newbss->max_num_sta; - } else - change.num_sta_remove = 0; - ap_for_each_sta(hapd, hostapd_config_reload_sta, &change); - - old_radius = hapd->radius; - hapd->radius = radius_client_reconfig(hapd->radius, hapd, - oldbss->radius, newbss->radius); - hapd->radius_client_reconfigured = old_radius != hapd->radius || - hostapd_ip_diff(&newbss->own_ip_addr, &oldbss->own_ip_addr); - - ieee802_1x_reconfig(hapd, oldconf, oldbss); - iapp_reconfig(hapd, oldconf, oldbss); - - hostapd_acl_reconfig(hapd, oldconf); - accounting_reconfig(hapd, oldconf); -} - - -/** - * config_reload2 - Part 2 of configuration reloading - * @hapd_iface: - */ -static void config_reload2(struct hostapd_iface *hapd_iface, int status) -{ - struct hostapd_config_change *change = hapd_iface->change; - struct hostapd_data *hapd = change->hapd; - struct hostapd_config *newconf = change->newconf; - struct hostapd_config *oldconf = change->oldconf; - int beacon_changed = change->beacon_changed; - struct hostapd_data **new_hapd = change->new_hapd; - struct hostapd_data **old_hapd = change->old_hapd; - int num_old_hapd = change->num_old_hapd; - size_t i, j, max_bss, same_bssid; - struct hostapd_bss_config *newbss, *oldbss; - u8 *prev_addr; - hostapd_iface_cb cb; - - free(change); - hapd_iface->change = NULL; - - if (status) { - printf("Failed to setup new interface config\n"); - - cb = hapd_iface->config_reload_cb; - hapd_iface->config_reload_cb = NULL; - - /* Invalid configuration - cleanup and terminate hostapd */ - hapd_iface->bss = old_hapd; - hapd_iface->num_bss = num_old_hapd; - hapd_iface->conf = hapd->iconf = oldconf; - hapd->conf = &oldconf->bss[0]; - hostapd_config_free(newconf); - free(new_hapd); - - cb(hapd_iface, -2); - - return; - } - - /* - * If any BSSes have been removed, added, or had their BSSIDs changed, - * completely remove and reinitialize such BSSes and all the BSSes - * following them since their BSSID might have changed. - */ - max_bss = oldconf->num_bss; - if (max_bss > newconf->num_bss) - max_bss = newconf->num_bss; - - for (i = 0; i < max_bss; i++) { - if (strcmp(oldconf->bss[i].iface, newconf->bss[i].iface) != 0 - || hostapd_mac_comp(oldconf->bss[i].bssid, - newconf->bss[i].bssid) != 0) - break; - } - same_bssid = i; - - for (i = 0; i < oldconf->num_bss; i++) { - oldbss = &oldconf->bss[i]; - newbss = NULL; - for (j = 0; j < newconf->num_bss; j++) { - if (strcmp(oldbss->iface, newconf->bss[j].iface) == 0) - { - newbss = &newconf->bss[j]; - break; - } - } - - if (newbss && i < same_bssid) { - hapd = hapd_iface->bss[j] = old_hapd[i]; - hapd->iconf = newconf; - hapd->conf = newbss; - hostapd_reconfig_bss(hapd, newbss, oldbss, oldconf, - beacon_changed); - } else { - hapd = old_hapd[i]; - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "Removing BSS (ifname %s)\n", - hapd->conf->iface); - hostapd_free_stas(hapd); - /* Send broadcast deauthentication for this BSS, but do - * not clear all STAs from the driver since other BSSes - * may have STA entries. The driver will remove all STA - * entries for this BSS anyway when the interface is - * being removed. */ -#if 0 - hostapd_deauth_all_stas(hapd); - hostapd_cleanup(hapd); -#endif - - free(hapd); - } - } - - - prev_addr = hapd_iface->bss[0]->own_addr; - hapd = hapd_iface->bss[0]; - for (j = 0; j < newconf->num_bss; j++) { - if (hapd_iface->bss[j] != NULL) { - prev_addr = hapd_iface->bss[j]->own_addr; - continue; - } - - newbss = &newconf->bss[j]; - - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Reconfiguration: adding " - "new BSS (ifname=%s)\n", newbss->iface); - -#if 0 - hapd = hapd_iface->bss[j] = - hostapd_alloc_bss_data(hapd_iface, newconf, newbss); -#endif - if (hapd == NULL) { - printf("Failed to initialize new BSS\n"); - /* FIX: This one is somewhat hard to recover - * from.. Would need to remove this BSS from - * conf and BSS list. */ - exit(1); - } - hapd->driver = hapd_iface->bss[0]->driver; - hapd->iface = hapd_iface; - hapd->iconf = newconf; - hapd->conf = newbss; - - memcpy(hapd->own_addr, prev_addr, ETH_ALEN); - if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0) - prev_addr = hapd->own_addr; - -#if 0 - if (hostapd_setup_bss(hapd, j == 0)) { - printf("Failed to setup new BSS\n"); - /* FIX */ - exit(1); - } -#endif - - } - - free(old_hapd); - hostapd_config_free(oldconf); - - cb = hapd_iface->config_reload_cb; - hapd_iface->config_reload_cb = NULL; - - cb(hapd_iface, 0); -} - - -/** - * hostapd_config_reload_start - Start reconfiguration of an interface - * @hapd_iface: Pointer to hostapd interface data - * @cb: Function to be called back when done. - * The status indicates: - * 0 = success, new configuration in use; - * -1 = failed to update configuraiton, old configuration in use; - * -2 = failed to update configuration and failed to recover; caller - * should cleanup and terminate hostapd - * Returns: - * 0 = reconfiguration started; - * -1 = failed to update configuration, old configuration in use; - * -2 = failed to update configuration and failed to recover; caller - * should cleanup and terminate hostapd - */ -int hostapd_config_reload_start(struct hostapd_iface *hapd_iface, - hostapd_iface_cb cb) -{ - struct hostapd_config *newconf, *oldconf; - struct hostapd_config_change *change; - struct hostapd_data *hapd = NULL; - struct hostapd_data **old_hapd, **new_hapd; - int num_old_hapd; - - if (hapd_iface->config_reload_cb) { - wpa_printf(MSG_DEBUG, "%s: Config reload already in progress.", - hapd_iface->bss[0]->conf->iface); - return -1; - } - - newconf = hostapd_config_read(hapd_iface->config_fname); - if (newconf == NULL) { - printf("Failed to read new configuration file - continuing " - "with old.\n"); - return -1; - } - - if (strcmp(newconf->bss[0].iface, hapd_iface->conf->bss[0].iface) != - 0) { - printf("Interface name changing is not allowed in " - "configuration reloading (%s -> %s).\n", - hapd_iface->conf->bss[0].iface, newconf->bss[0].iface); - hostapd_config_free(newconf); - return -1; - } - - new_hapd = wpa_zalloc(newconf->num_bss * - sizeof(struct hostapd_data *)); - if (new_hapd == NULL) { - hostapd_config_free(newconf); - return -1; - } - old_hapd = hapd_iface->bss; - num_old_hapd = hapd_iface->num_bss; - - hapd_iface->bss = new_hapd; - hapd_iface->num_bss = newconf->num_bss; - /* - * First BSS remains the same since interface name changing was - * prohibited above. Now, this is only used in - * hostapd_config_reload_iface() and following loop will anyway set - * this again. - */ - hapd = hapd_iface->bss[0] = old_hapd[0]; - - oldconf = hapd_iface->conf; - hapd->iconf = hapd_iface->conf = newconf; - hapd->conf = &newconf->bss[0]; - - change = wpa_zalloc(sizeof(struct hostapd_config_change)); - if (change == NULL) { - hostapd_config_free(newconf); - return -1; - } - - change->hapd = hapd; - change->newconf = newconf; - change->oldconf = oldconf; - change->beacon_changed = 0; - change->hapd_iface = hapd_iface; - change->new_hapd = new_hapd; - change->old_hapd = old_hapd; - change->num_old_hapd = num_old_hapd; - - hapd_iface->config_reload_cb = cb; - hapd_iface->change = change; - if (hostapd_config_reload_iface_start(hapd_iface, config_reload2)) { - printf("Failed to start setup of new interface config\n"); - - hapd_iface->config_reload_cb = NULL; - free(change); - hapd_iface->change = NULL; - - /* Invalid configuration - cleanup and terminate hostapd */ - hapd_iface->bss = old_hapd; - hapd_iface->num_bss = num_old_hapd; - hapd_iface->conf = hapd->iconf = oldconf; - hapd->conf = &oldconf->bss[0]; - hostapd_config_free(newconf); - free(new_hapd); - return -2; - } - - return 0; -} diff --git a/contrib/hostapd/sha1.c b/contrib/hostapd/sha1.c deleted file mode 100644 index 194db1601d1e..000000000000 --- a/contrib/hostapd/sha1.c +++ /dev/null @@ -1,722 +0,0 @@ -/* - * SHA1 hash implementation and interface functions - * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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" - - -/** - * 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) - */ -void 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; - } - - /* if key is longer than 64 bytes reset it to key = SHA1(key) */ - if (key_len > 64) { - sha1_vector(1, &key, &key_len, tk); - 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]; - } - sha1_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 SHA1 */ - _addr[0] = k_pad; - _len[0] = 64; - _addr[1] = mac; - _len[1] = SHA1_MAC_LEN; - 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) - */ -void hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len, - u8 *mac) -{ - 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 - * - * This function is used to derive new, cryptographically separate keys from a - * given key (e.g., PMK in IEEE 802.11i). - */ -void 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 zero = 0, counter = 0; - size_t pos, plen; - u8 hash[SHA1_MAC_LEN]; - size_t label_len = os_strlen(label); - const unsigned char *addr[4]; - size_t len[4]; - - addr[0] = (u8 *) label; - len[0] = label_len; - addr[1] = &zero; - len[1] = 1; - addr[2] = data; - len[2] = data_len; - addr[3] = &counter; - 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++; - } -} - - -/** - * 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 - * - * This function is used to derive new, cryptographically separate keys from a - * given key for EAP-FAST. T-PRF is defined in - * draft-cam-winget-eap-fast-02.txt, Appendix B. - */ -void 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; - 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; - } -} - - -/** - * 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; - - hmac_md5_vector(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(S1, L_S1, 3, MD5_addr, MD5_len, P_MD5); - MD5_pos = 0; - hmac_md5(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; -} - - -static void 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; - hmac_sha1_vector((u8 *) passphrase, passphrase_len, 2, addr, len, tmp); - os_memcpy(digest, tmp, SHA1_MAC_LEN); - - for (i = 1; i < iterations; i++) { - hmac_sha1((u8 *) passphrase, passphrase_len, tmp, SHA1_MAC_LEN, - tmp2); - os_memcpy(tmp, tmp2, SHA1_MAC_LEN); - for (j = 0; j < SHA1_MAC_LEN; j++) - digest[j] ^= tmp2[j]; - } -} - - -/** - * pbkdf2_sha1 - SHA1-based key derivation function (PBKDF2) for IEEE 802.11i - * @passphrase: ASCII passphrase - * @ssid: SSID - * @ssid_len: SSID length in bytes - * @interations: Number of iterations to run - * @buf: Buffer for the generated key - * @buflen: Length of the buffer in bytes - * - * 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. - */ -void 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++; - pbkdf2_sha1_f(passphrase, ssid, ssid_len, iterations, count, - digest); - plen = left > SHA1_MAC_LEN ? SHA1_MAC_LEN : left; - os_memcpy(pos, digest, plen); - pos += plen; - left -= plen; - } -} - - -#ifdef INTERNAL_SHA1 - -struct SHA1Context { - u32 state[5]; - u32 count[2]; - unsigned char buffer[64]; -}; - -typedef struct SHA1Context SHA1_CTX; - -#ifndef CONFIG_CRYPTO_INTERNAL -static void SHA1Init(struct SHA1Context *context); -static void SHA1Update(struct SHA1Context *context, const void *data, u32 len); -static void SHA1Final(unsigned char digest[20], struct SHA1Context *context); -#endif /* CONFIG_CRYPTO_INTERNAL */ -static 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 - */ -void 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); -} - - -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; -} - - -/* ===== start - public domain SHA1 implementation ===== */ - -/* -SHA-1 in C -By Steve Reid <sreid@sea-to-sky.net> -100% Public Domain - ------------------ -Modified 7/98 -By James H. Brown <jbrown@burgoyne.com> -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 <process.h> 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 <sreid@sea-to-sky.net> -Still 100% public domain - -1- Removed #include <process.h> 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 <Saul.Kravitz@celera.com> -Still 100% PD -Modified to run on Compaq Alpha hardware. - ------------------ -Modified 4/01 -By Jouni Malinen <j@w1.fi> -Minor changes to match the coding style used in Dynamics. - -Modified September 24, 2004 -By Jouni Malinen <j@w1.fi> -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. */ - -static 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 - u32 workspace[16]; - block = (CHAR64LONG16 *) 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 ===== */ - -#endif /* INTERNAL_SHA1 */ diff --git a/contrib/hostapd/sha1.h b/contrib/hostapd/sha1.h deleted file mode 100644 index 97affa1a620d..000000000000 --- a/contrib/hostapd/sha1.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * SHA1 hash implementation and interface functions - * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 - -void hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac); -void hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len, - u8 *mac); -void 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); -void 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 tls_prf(const u8 *secret, size_t secret_len, const char *label, - const u8 *seed, size_t seed_len, u8 *out, size_t outlen); -void pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len, - int iterations, u8 *buf, size_t buflen); - -#ifdef CONFIG_CRYPTO_INTERNAL -struct SHA1Context; - -void SHA1Init(struct SHA1Context *context); -void SHA1Update(struct SHA1Context *context, const void *data, u32 len); -void SHA1Final(unsigned char digest[20], struct SHA1Context *context); -#endif /* CONFIG_CRYPTO_INTERNAL */ - -#endif /* SHA1_H */ diff --git a/contrib/hostapd/sha256.c b/contrib/hostapd/sha256.c deleted file mode 100644 index 175ec8b637da..000000000000 --- a/contrib/hostapd/sha256.c +++ /dev/null @@ -1,379 +0,0 @@ -/* - * SHA-256 hash implementation and interface functions - * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 */ - memset(k_pad, 0, sizeof(k_pad)); - 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); - - memset(k_pad, 0, sizeof(k_pad)); - 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.5A.3) - * @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 = 0; - size_t pos, plen; - u8 hash[SHA256_MAC_LEN]; - const u8 *addr[3]; - size_t len[3]; - u8 counter_le[2]; - - addr[0] = counter_le; - len[0] = 2; - addr[1] = (u8 *) label; - len[1] = strlen(label) + 1; - addr[2] = data; - len[2] = data_len; - - 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, 3, addr, len, - &buf[pos]); - pos += SHA256_MAC_LEN; - } else { - hmac_sha256_vector(key, key_len, 3, addr, len, hash); - memcpy(&buf[pos], hash, plen); - break; - } - counter++; - } -} - - -#ifdef INTERNAL_SHA256 - -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 - */ -void 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++) - sha256_process(&ctx, addr[i], len[i]); - sha256_done(&ctx, mac); -} - - -/* ===== 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)); - 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 ===== */ - -#endif /* INTERNAL_SHA256 */ diff --git a/contrib/hostapd/sha256.h b/contrib/hostapd/sha256.h deleted file mode 100644 index dc597f09b53a..000000000000 --- a/contrib/hostapd/sha256.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * SHA256 hash implementation and interface functions - * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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/contrib/hostapd/sta_info.c b/contrib/hostapd/sta_info.c deleted file mode 100644 index dbb7f6cef719..000000000000 --- a/contrib/hostapd/sta_info.c +++ /dev/null @@ -1,585 +0,0 @@ -/* - * hostapd / Station table - * Copyright (c) 2002-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "hostapd.h" -#include "sta_info.h" -#include "eloop.h" -#include "accounting.h" -#include "ieee802_1x.h" -#include "ieee802_11.h" -#include "radius.h" -#include "eapol_sm.h" -#include "wpa.h" -#include "preauth.h" -#include "radius_client.h" -#include "driver.h" -#include "beacon.h" -#include "hw_features.h" -#include "mlme.h" -#include "vlan_init.h" - -static int ap_sta_in_other_bss(struct hostapd_data *hapd, - struct sta_info *sta, u32 flags); -static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx); - -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 && 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) { - printf("Could not remove STA " MACSTR " from list.\n", - 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 (memcmp(s->addr, sta->addr, 6) == 0) { - hapd->sta_hash[STA_HASH(sta->addr)] = s->hnext; - return; - } - - while (s->hnext != NULL && memcmp(s->hnext->addr, sta->addr, 6) != 0) - s = s->hnext; - if (s->hnext != NULL) - s->hnext = s->hnext->hnext; - else - printf("AP: could not remove STA " MACSTR " from hash table\n", - MAC2STR(sta->addr)); -} - - -void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) -{ - int set_beacon = 0; - - accounting_sta_stop(hapd, sta); - - if (!ap_sta_in_other_bss(hapd, sta, WLAN_STA_ASSOC) && - !(sta->flags & WLAN_STA_PREAUTH)) - hostapd_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] = NULL; - - 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 (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); - radius_client_flush_auth(hapd->radius, sta->addr); - - if (sta->last_assoc_req) - free(sta->last_assoc_req); - - free(sta->challenge); - - 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; - printf("Removing station " MACSTR "\n", MAC2STR(prev->addr)); - ap_free_sta(hapd, prev); - } -} - - -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; - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - "Checking STA " MACSTR " inactivity:\n", - MAC2STR(sta->addr)); - inactive_sec = hostapd_get_inact_sec(hapd, sta->addr); - if (inactive_sec == -1) { - printf(" Could not get station info from kernel " - "driver for " MACSTR ".\n", - MAC2STR(sta->addr)); - } else if (inactive_sec < hapd->conf->ap_max_inactivity && - sta->flags & WLAN_STA_ASSOC) { - /* station activity detected; reset timeout state */ - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - " Station has been active\n"); - sta->timeout_next = STA_NULLFUNC; - next_time = hapd->conf->ap_max_inactivity - - inactive_sec; - } - } - - if ((sta->flags & WLAN_STA_ASSOC) && - sta->timeout_next == STA_DISASSOC && - !(sta->flags & WLAN_STA_PENDING_POLL)) { - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - " Station has ACKed data poll\n"); - /* 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)) { - /* send data frame to poll STA and check whether this frame - * is ACKed */ - struct ieee80211_hdr hdr; - - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, - " Polling STA with data frame\n"); - sta->flags |= WLAN_STA_PENDING_POLL; - -#ifndef CONFIG_NATIVE_WINDOWS - /* FIX: WLAN_FC_STYPE_NULLFUNC would be more appropriate, but - * it is apparently not retried so TX Exc events are not - * received for it */ - memset(&hdr, 0, sizeof(hdr)); - hdr.frame_control = - IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA); - hdr.frame_control |= host_to_le16(BIT(1)); - hdr.frame_control |= host_to_le16(WLAN_FC_FROMDS); - memcpy(hdr.IEEE80211_DA_FROMDS, sta->addr, ETH_ALEN); - memcpy(hdr.IEEE80211_BSSID_FROMDS, hapd->own_addr, ETH_ALEN); - memcpy(hdr.IEEE80211_SA_FROMDS, hapd->own_addr, ETH_ALEN); - - if (hostapd_send_mgmt_frame(hapd, &hdr, sizeof(hdr), 0) < 0) - perror("ap_handle_timer: send"); -#endif /* CONFIG_NATIVE_WINDOWS */ - } else if (sta->timeout_next != STA_REMOVE) { - int deauth = sta->timeout_next == STA_DEAUTH; - - printf(" Sending %s info to STA " MACSTR "\n", - deauth ? "deauthentication" : "disassociation", - MAC2STR(sta->addr)); - - if (deauth) { - hostapd_sta_deauth(hapd, sta->addr, - WLAN_REASON_PREV_AUTH_NOT_VALID); - } else { - hostapd_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; - memcpy(addr, sta->addr, ETH_ALEN); - ap_free_sta(hapd, sta); - hostapd_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; - - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, " New STA\n"); - if (hapd->num_sta >= hapd->conf->max_num_sta) { - /* FIX: might try to remove some old STAs first? */ - printf(" no more room for new STAs (%d/%d)\n", - hapd->num_sta, hapd->conf->max_num_sta); - return NULL; - } - - sta = wpa_zalloc(sizeof(struct sta_info)); - if (sta == NULL) { - printf(" malloc failed\n"); - return NULL; - } - sta->acct_interim_interval = hapd->conf->radius->acct_interim_interval; - - /* initialize STA info data */ - eloop_register_timeout(hapd->conf->ap_max_inactivity, 0, - ap_handle_timer, hapd, sta); - 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; - - return sta; -} - - -static int ap_sta_remove(struct hostapd_data *hapd, struct sta_info *sta) -{ - ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); - - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Removing STA " MACSTR - " from kernel driver\n", MAC2STR(sta->addr)); - if (hostapd_sta_remove(hapd, sta->addr) && - sta->flags & WLAN_STA_ASSOC) { - printf("Could not remove station " MACSTR " from kernel " - "driver.\n", MAC2STR(sta->addr)); - return -1; - } - return 0; -} - - -static int ap_sta_in_other_bss(struct hostapd_data *hapd, - struct sta_info *sta, u32 flags) -{ - 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 && ((sta2->flags & flags) == flags)) - return 1; - } - - return 0; -} - - -void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta, - u16 reason) -{ - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "%s: disassociate STA " MACSTR - "\n", hapd->conf->iface, MAC2STR(sta->addr)); - sta->flags &= ~WLAN_STA_ASSOC; - if (!ap_sta_in_other_bss(hapd, sta, 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) -{ - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "%s: deauthenticate STA " MACSTR - "\n", hapd->conf->iface, MAC2STR(sta->addr)); - sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); - if (!ap_sta_in_other_bss(hapd, sta, 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) -{ - const char *iface; - struct hostapd_vlan *vlan = NULL; - - /* - * 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"); - - return hostapd_set_sta_vlan(iface, hapd, sta->addr, sta->vlan_id); -} diff --git a/contrib/hostapd/sta_info.h b/contrib/hostapd/sta_info.h deleted file mode 100644 index 1d9ab9687ab8..000000000000 --- a/contrib/hostapd/sta_info.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * hostapd / Station table - * Copyright (c) 2002-2004, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 - -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); - -#endif /* STA_INFO_H */ diff --git a/contrib/hostapd/state_machine.h b/contrib/hostapd/state_machine.h deleted file mode 100644 index 62766bf40ba4..000000000000 --- a/contrib/hostapd/state_machine.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * wpa_supplicant/hostapd - State machine definitions - * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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/contrib/hostapd/tls.h b/contrib/hostapd/tls.h deleted file mode 100644 index 30d8842837fc..000000000000 --- a/contrib/hostapd/tls.h +++ /dev/null @@ -1,521 +0,0 @@ -/* - * WPA Supplicant / SSL/TLS interface definition - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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; -}; - -struct tls_config { - const char *opensc_engine_path; - const char *pkcs11_engine_path; - const char *pkcs11_module_path; -}; - -/** - * 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 key id (this is OpenSSL specific for now) - * @tls_ia: Whether to enable TLS/IA (for EAP-TTLSv1) - * - * 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; -}; - - -/** - * 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 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 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 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 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 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 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 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 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 - * - * Caller is responsible for freeing 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. 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. - */ -u8 * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len, u8 **appl_data, - size_t *appl_data_len); - -/** - * 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 - * @in_len: Input data length - * @out_len: Length of the output buffer. - * Returns: pointer to output data, %NULL on failure - * - * Caller is responsible for freeing returned output data. - */ -u8 * tls_connection_server_handshake(void *tls_ctx, - struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len); - -/** - * 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: 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 tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len); - -/** - * 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: 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 tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len); - -/** - * 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); - -/** - * tls_connection_set_master_key - Configure master secret for TLS connection - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @key: TLS pre-master-secret - * @key_len: length of key in bytes - * Returns: 0 on success, -1 on failure - */ -int tls_connection_set_master_key(void *tls_ctx, struct tls_connection *conn, - const u8 *key, size_t key_len); - -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 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 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 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 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 - * @out_data: Pointer to output buffer (encrypted TLS/IA data) - * @out_len: Maximum out_data length - * Returns: Number of bytes written to out_data on success, -1 on failure - * - * This function is used to send the TLS/IA end phase message, e.g., when the - * EAP server completes EAP-TTLSv1. - */ -int tls_connection_ia_send_phase_finished(void *tls_ctx, - struct tls_connection *conn, - int final, - u8 *out_data, size_t out_len); - -/** - * 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 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 tls_connection_ia_permute_inner_secret(void *tls_ctx, - struct tls_connection *conn, - const u8 *key, size_t key_len); - -#endif /* TLS_H */ diff --git a/contrib/hostapd/tls_gnutls.c b/contrib/hostapd/tls_gnutls.c deleted file mode 100644 index 07893983189d..000000000000 --- a/contrib/hostapd/tls_gnutls.c +++ /dev/null @@ -1,1370 +0,0 @@ -/* - * WPA Supplicant / SSL/TLS interface functions for openssl - * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 <gnutls/gnutls.h> -#include <gnutls/x509.h> -#ifdef PKCS12_FUNCS -#include <gnutls/pkcs12.h> -#endif /* PKCS12_FUNCS */ - -#ifdef CONFIG_GNUTLS_EXTRA -#if LIBGNUTLS_VERSION_NUMBER >= 0x010302 -#define GNUTLS_IA -#include <gnutls/extra.h> -#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" - - -#define TLS_RANDOM_SIZE 32 -#define TLS_MASTER_SIZE 48 - - -#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; - - u8 *push_buf, *pull_buf, *pull_buf_offset; - size_t push_buf_len, pull_buf_len; - - 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; - u8 *end; - if (conn->pull_buf == NULL) { - errno = EWOULDBLOCK; - return -1; - } - - end = conn->pull_buf + conn->pull_buf_len; - 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__); - os_free(conn->pull_buf); - conn->pull_buf = conn->pull_buf_offset = NULL; - conn->pull_buf_len = 0; - } else { - wpa_printf(MSG_DEBUG, "%s - %d bytes remaining in pull_buf", - __func__, 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; - u8 *nbuf; - - nbuf = os_realloc(conn->push_buf, conn->push_buf_len + len); - if (nbuf == NULL) { - errno = ENOMEM; - return -1; - } - os_memcpy(nbuf + conn->push_buf_len, buf, len); - conn->push_buf = nbuf; - conn->push_buf_len += 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); - os_free(conn->push_buf); - os_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); - os_free(conn->push_buf); - conn->push_buf = NULL; - conn->push_buf_len = 0; - 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->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->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) -{ - 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"); - return -1; - } - - if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) { - wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted"); - return -1; - } - - if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) { - wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a " - "known issuer"); - return -1; - } - - if (status & GNUTLS_CERT_REVOKED) { - wpa_printf(MSG_INFO, "TLS: Peer certificate has been 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"); - 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"); - 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); - 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); - return -1; - } - - gnutls_x509_crt_deinit(cert); - } - - return 0; -} - - -u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len, u8 **appl_data, - size_t *appl_data_len) -{ - struct tls_global *global = ssl_ctx; - u8 *out_data; - int ret; - - if (appl_data) - *appl_data = NULL; - - if (in_data && in_len) { - if (conn->pull_buf) { - wpa_printf(MSG_DEBUG, "%s - %d bytes remaining in " - "pull_buf", __func__, conn->pull_buf_len); - os_free(conn->pull_buf); - } - conn->pull_buf = os_malloc(in_len); - if (conn->pull_buf == NULL) - return NULL; - os_memcpy(conn->pull_buf, in_data, in_len); - conn->pull_buf_offset = conn->pull_buf; - conn->pull_buf_len = in_len; - } - - 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 = os_malloc(1); - } - 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; - - if (conn->verify_peer && tls_connection_verify_peer(conn)) { - wpa_printf(MSG_INFO, "TLS: Peer certificate chain " - "failed validation"); - conn->failed++; - return NULL; - } - - if (conn->tls_ia && !gnutls_ia_handshake_p(conn->session)) { - wpa_printf(MSG_INFO, "TLS: No TLS/IA negotiation"); - conn->failed++; - return NULL; - } - - 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 = os_malloc(1); - } - - 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); - } - } - - out_data = conn->push_buf; - *out_len = conn->push_buf_len; - conn->push_buf = NULL; - conn->push_buf_len = 0; - return out_data; -} - - -u8 * tls_connection_server_handshake(void *ssl_ctx, - struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len) -{ - return tls_connection_handshake(ssl_ctx, conn, in_data, in_len, - out_len, NULL, NULL); -} - - -int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ - ssize_t res; - -#ifdef GNUTLS_IA - if (conn->tls_ia) - res = gnutls_ia_send(conn->session, (char *) in_data, in_len); - else -#endif /* GNUTLS_IA */ - res = gnutls_record_send(conn->session, in_data, in_len); - if (res < 0) { - wpa_printf(MSG_INFO, "%s: Encryption failed: %s", - __func__, gnutls_strerror(res)); - return -1; - } - if (conn->push_buf == NULL) - return -1; - if (conn->push_buf_len < out_len) - out_len = conn->push_buf_len; - os_memcpy(out_data, conn->push_buf, out_len); - os_free(conn->push_buf); - conn->push_buf = NULL; - conn->push_buf_len = 0; - return out_len; -} - - -int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ - ssize_t res; - - if (conn->pull_buf) { - wpa_printf(MSG_DEBUG, "%s - %d bytes remaining in " - "pull_buf", __func__, conn->pull_buf_len); - os_free(conn->pull_buf); - } - conn->pull_buf = os_malloc(in_len); - if (conn->pull_buf == NULL) - return -1; - os_memcpy(conn->pull_buf, in_data, in_len); - conn->pull_buf_offset = conn->pull_buf; - conn->pull_buf_len = in_len; - -#ifdef GNUTLS_IA - if (conn->tls_ia) { - res = gnutls_ia_recv(conn->session, (char *) out_data, - out_len); - if (out_len >= 12 && - (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)); - return -1; - } - - res = gnutls_ia_verify_endphase(conn->session, - (char *) out_data); - 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)); - return -1; - } - - if (final) - conn->final_phase_finished = 1; - - return 0; - } - - if (res < 0) { - wpa_printf(MSG_DEBUG, "%s - gnutls_ia_recv failed: %d " - "(%s)", __func__, res, - gnutls_strerror(res)); - } - return res; - } -#endif /* GNUTLS_IA */ - - res = gnutls_record_recv(conn->session, out_data, out_len); - if (res < 0) { - wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d " - "(%s)", __func__, res, gnutls_strerror(res)); - } - - return res; -} - - -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_master_key(void *ssl_ctx, struct tls_connection *conn, - const u8 *key, size_t key_len) -{ - /* TODO */ - return -1; -} - - -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) -{ - /* TODO: set SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS */ - 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 */ -} - - -int tls_connection_ia_send_phase_finished(void *tls_ctx, - struct tls_connection *conn, - int final, - u8 *out_data, size_t out_len) -{ -#ifdef GNUTLS_IA - int ret; - - if (conn == NULL || conn->session == NULL || !conn->tls_ia) - return -1; - - 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 -1; - } - - 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 -1; - } - - if (conn->push_buf == NULL) - return -1; - if (conn->push_buf_len < out_len) - out_len = conn->push_buf_len; - os_memcpy(out_data, conn->push_buf, out_len); - os_free(conn->push_buf); - conn->push_buf = NULL; - conn->push_buf_len = 0; - return out_len; -#else /* GNUTLS_IA */ - return -1; -#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 */ -} diff --git a/contrib/hostapd/tls_none.c b/contrib/hostapd/tls_none.c deleted file mode 100644 index ad08d5076c88..000000000000 --- a/contrib/hostapd/tls_none.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * WPA Supplicant / SSL/TLS interface functions for no TLS case - * Copyright (c) 2004, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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) -{ -} - - -#ifdef EAP_TLS_NONE - -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; -} - - -u8 * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len, u8 **appl_data, - size_t *appl_data_len) -{ - return NULL; -} - - -u8 * tls_connection_server_handshake(void *tls_ctx, - struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len) -{ - return NULL; -} - - -int tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ - return -1; -} - - -int tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ - return -1; -} - - -int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn) -{ - return 0; -} - - -int tls_connection_set_master_key(void *tls_ctx, struct tls_connection *conn, - const u8 *key, size_t key_len) -{ - return -1; -} - - -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; -} - - -int tls_connection_ia_send_phase_finished(void *tls_ctx, - struct tls_connection *conn, - int final, - u8 *out_data, size_t out_len) -{ - return -1; -} - - -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; -} - -#endif /* EAP_TLS_NONE */ diff --git a/contrib/hostapd/tls_openssl.c b/contrib/hostapd/tls_openssl.c deleted file mode 100644 index d5aafaaa89d4..000000000000 --- a/contrib/hostapd/tls_openssl.c +++ /dev/null @@ -1,2333 +0,0 @@ -/* - * WPA Supplicant / SSL/TLS interface functions for openssl - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 <openssl/ssl.h> -#include <openssl/err.h> -#include <openssl/pkcs12.h> -#include <openssl/x509v3.h> -#ifndef OPENSSL_NO_ENGINE -#include <openssl/engine.h> -#endif /* OPENSSL_NO_ENGINE */ - -#include "common.h" -#include "tls.h" - -#if OPENSSL_VERSION_NUMBER >= 0x0090800fL -#define OPENSSL_d2i_TYPE const unsigned char ** -#else -#define OPENSSL_d2i_TYPE unsigned char ** -#endif - -static int tls_openssl_ref_count = 0; - -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; - - u8 *pre_shared_secret; - size_t pre_shared_secret_len; -}; - - -#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 <wincrypt.h> - -#ifdef __MINGW32_VERSION -/* - * MinGW does not yet include all the needed definitions for CryptoAPI, so - * define here whatever extra is needed. - */ -#define CALG_SSL3_SHAMD5 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SSL3SHAMD5) -#define CERT_SYSTEM_STORE_CURRENT_USER (1 << 16) -#define CERT_STORE_READONLY_FLAG 0x00008000 -#define CERT_STORE_OPEN_EXISTING_FLAG 0x00004000 -#define CRYPT_ACQUIRE_COMPARE_KEY_FLAG 0x00000004 - -static BOOL WINAPI -(*CryptAcquireCertificatePrivateKey)(PCCERT_CONTEXT pCert, DWORD dwFlags, - void *pvReserved, HCRYPTPROV *phCryptProv, - DWORD *pdwKeySpec, BOOL *pfCallerFreeProv) -= NULL; /* to be loaded from crypt32.dll */ - -static PCCERT_CONTEXT WINAPI -(*CertEnumCertificatesInStore)(HCERTSTORE hCertStore, - PCCERT_CONTEXT pPrevCertContext) -= 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 (CryptAcquireCertificatePrivateKey) - return 0; - - dll = LoadLibrary("crypt32"); - if (dll == NULL) { - wpa_printf(MSG_DEBUG, "CryptoAPI: Could not load crypt32 " - "library"); - return -1; - } - - CryptAcquireCertificatePrivateKey = GetProcAddress( - dll, "CryptAcquireCertificatePrivateKey"); - if (CryptAcquireCertificatePrivateKey == NULL) { - wpa_printf(MSG_DEBUG, "CryptoAPI: Could not get " - "CryptAcquireCertificatePrivateKey() address from " - "crypt32 library"); - return -1; - } - - CertEnumCertificatesInStore = (void *) GetProcAddress( - dll, "CertEnumCertificatesInStore"); - if (CertEnumCertificatesInStore == NULL) { - wpa_printf(MSG_DEBUG, "CryptoAPI: Could not get " - "CertEnumCertificatesInStore() address from " - "crypt32 library"); - return -1; - } - - return 0; -} - -#else /* __MINGW32_VERSION */ - -static int mingw_load_crypto_func(void) -{ - return 0; -} - -#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 (mingw_load_crypto_func()) - 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 (mingw_load_crypto_func()) - return -1; - - 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) { - SSL_load_error_strings(); - SSL_library_init(); - /* 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 - 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 */ - ERR_free_strings(); - EVP_cleanup(); - } -} - - -static int tls_engine_init(struct tls_connection *conn, const char *engine_id, - const char *pin, const char *key_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; - } - 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; - } - 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; - - 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); - SSL_set_options(conn->ssl, - SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | - SSL_OP_SINGLE_DH_USE); - - 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; - os_free(conn->pre_shared_secret); - SSL_free(conn->ssl); - tls_engine_deinit(conn); - os_free(conn->subject_match); - os_free(conn->altsubject_match); - 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 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 && os_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; -} - - -#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 */ - - -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; - } - - 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__); - SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb); - return 0; - } - -#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"); - SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb); - 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); - } - SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb); -#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 */ - SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL); - } - - 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) -{ - if (conn == NULL) - return -1; - - if (verify_peer) { - SSL_set_verify(conn->ssl, SSL_VERIFY_PEER | - SSL_VERIFY_FAIL_IF_NO_PEER_CERT | - SSL_VERIFY_CLIENT_ONCE, tls_verify_cb); - } else { - SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL); - } - - SSL_set_accept_state(conn->ssl); - - 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; - -#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; - } else { - tls_show_errors(MSG_DEBUG, __func__, - "SSL_use_certificate_file (DER) failed"); - } - - if (SSL_use_certificate_file(conn->ssl, client_cert, - SSL_FILETYPE_PEM) == 1) { - wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_file (PEM)" - " --> OK"); - return 0; - } else { - tls_show_errors(MSG_DEBUG, __func__, - "SSL_use_certificate_file (PEM) 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_strncpy(buf, (char *) password, size); - buf[size - 1] = '\0'; - 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 */ -} - - -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; - } else { - tls_show_errors(MSG_DEBUG, __func__, - "SSL_use_PrivateKey_ASN1(EVP_PKEY_RSA)" - " failed"); - } - - 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; - } else { - tls_show_errors(MSG_DEBUG, __func__, - "SSL_use_PrivateKey_ASN1(EVP_PKEY_DSA)" - " failed"); - } - - 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; - } else { - tls_show_errors(MSG_DEBUG, __func__, - "SSL_use_RSAPrivateKey_ASN1 failed"); - } - - 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; - } - - 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; - } else { - tls_show_errors(MSG_DEBUG, __func__, - "SSL_use_PrivateKey_File (DER) " - "failed"); - } - - 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 { - tls_show_errors(MSG_DEBUG, __func__, - "SSL_use_PrivateKey_File (PEM) " - "failed"); - } -#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) { - wpa_printf(MSG_INFO, "OpenSSL: Failed to load private key"); - os_free(passwd); - ERR_clear_error(); - 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 */ -} - - -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; -} - - -u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len, u8 **appl_data, - size_t *appl_data_len) -{ - int res; - u8 *out_data; - - if (appl_data) - *appl_data = NULL; - - /* - * Give TLS handshake data from the server (if available) to OpenSSL - * for processing. - */ - if (in_data && - BIO_write(conn->ssl_in, in_data, in_len) < 0) { - tls_show_errors(MSG_INFO, __func__, - "Handshake failed - BIO_write"); - return NULL; - } - - /* Initiate TLS handshake or continue the existing handshake */ - 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 = os_malloc(res == 0 ? 1 : 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"); - } - *out_len = 0; - return NULL; - } - res = res == 0 ? 0 : BIO_read(conn->ssl_out, 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"); - } - *out_len = 0; - return NULL; - } - *out_len = res; - - if (SSL_is_init_finished(conn->ssl) && appl_data) { - *appl_data = os_malloc(in_len); - if (*appl_data) { - res = SSL_read(conn->ssl, *appl_data, in_len); - if (res < 0) { - tls_show_errors(MSG_INFO, __func__, - "Failed to read possible " - "Application Data"); - os_free(*appl_data); - *appl_data = NULL; - } else { - *appl_data_len = res; - wpa_hexdump_key(MSG_MSGDUMP, "SSL: Application" - " Data in Finish message", - *appl_data, *appl_data_len); - } - } - } - - return out_data; -} - - -u8 * tls_connection_server_handshake(void *ssl_ctx, - struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len) -{ - int res; - u8 *out_data; - char buf[10]; - - if (in_data && - BIO_write(conn->ssl_in, in_data, in_len) < 0) { - tls_show_errors(MSG_INFO, __func__, - "Handshake failed - BIO_write"); - return NULL; - } - - res = SSL_read(conn->ssl, buf, sizeof(buf)); - if (res >= 0) { - wpa_printf(MSG_DEBUG, "SSL: Unexpected data from SSL_read " - "(res=%d)", res); - } - - res = BIO_ctrl_pending(conn->ssl_out); - wpa_printf(MSG_DEBUG, "SSL: %d bytes pending from ssl_out", res); - out_data = os_malloc(res == 0 ? 1 : 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"); - } - *out_len = 0; - return NULL; - } - res = res == 0 ? 0 : BIO_read(conn->ssl_out, 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"); - } - *out_len = 0; - return NULL; - } - *out_len = res; - return out_data; -} - - -int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ - int res; - - if (conn == NULL) - return -1; - - /* 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 res; - } - res = SSL_write(conn->ssl, in_data, in_len); - if (res < 0) { - tls_show_errors(MSG_INFO, __func__, - "Encryption failed - SSL_write"); - return res; - } - - /* Read encrypted data to be sent to the server */ - res = BIO_read(conn->ssl_out, out_data, out_len); - if (res < 0) { - tls_show_errors(MSG_INFO, __func__, - "Encryption failed - BIO_read"); - return res; - } - - return res; -} - - -int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ - int res; - - /* Give encrypted data from TLS tunnel for OpenSSL to decrypt. */ - res = BIO_write(conn->ssl_in, in_data, in_len); - if (res < 0) { - tls_show_errors(MSG_INFO, __func__, - "Decryption failed - BIO_write"); - return res; - } - if (BIO_reset(conn->ssl_out) < 0) { - tls_show_errors(MSG_INFO, __func__, "BIO_reset failed"); - return res; - } - - /* Read decrypted data for further processing */ - res = SSL_read(conn->ssl, out_data, out_len); - if (res < 0) { - tls_show_errors(MSG_INFO, __func__, - "Decryption failed - SSL_read"); - return res; - } - - return res; -} - - -int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn) -{ - return conn ? conn->ssl->hit : 0; -} - - -#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) -/* 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; - - if (conn == NULL || conn->pre_shared_secret == 0) - return 0; - - os_memcpy(secret, conn->pre_shared_secret, - conn->pre_shared_secret_len); - *secret_len = conn->pre_shared_secret_len; - - return 1; -} - - -int tls_connection_set_master_key(void *ssl_ctx, struct tls_connection *conn, - const u8 *key, size_t key_len) -{ - if (conn == NULL || key_len > SSL_MAX_MASTER_KEY_LENGTH) - return -1; - - os_free(conn->pre_shared_secret); - conn->pre_shared_secret = NULL; - conn->pre_shared_secret_len = 0; - - if (key) { - conn->pre_shared_secret = os_malloc(key_len); - if (conn->pre_shared_secret) { - os_memcpy(conn->pre_shared_secret, key, key_len); - conn->pre_shared_secret_len = key_len; - } - if (SSL_set_session_secret_cb(conn->ssl, tls_sess_sec_cb, - conn) != 1) - return -1; - } else { - if (SSL_set_session_secret_cb(conn->ssl, NULL, NULL) != 1) - return -1; - } - - return 0; -} -#endif /* EAP_FAST || EAP_FAST_DYNAMIC */ - - -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_snprintf(buf, buflen, "%s", name); - buf[buflen - 1] = '\0'; - 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) -/* 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) - return -1; - - if (SSL_set_hello_extension(conn->ssl, ext_type, (void *) data, - data_len) != 1) - return -1; - - return 0; -} -#endif /* EAP_FAST || EAP_FAST_DYNAMIC */ - - -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 (tls_connection_set_subject_match(conn, - params->subject_match, - params->altsubject_match)) - return -1; - 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 (tls_connection_client_cert(conn, params->client_cert, - params->client_cert_blob, - params->client_cert_blob_len)) - return -1; - - if (params->engine) { - wpa_printf(MSG_DEBUG, "SSL: Initializing TLS engine"); - ret = tls_engine_init(conn, params->engine_id, params->pin, - params->key_id); - if (ret) - return ret; - 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; - - 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; -} - - -int tls_connection_ia_send_phase_finished(void *tls_ctx, - struct tls_connection *conn, - int final, - u8 *out_data, size_t out_len) -{ - return -1; -} - - -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/contrib/hostapd/version.h b/contrib/hostapd/version.h deleted file mode 100644 index 364d8aea9657..000000000000 --- a/contrib/hostapd/version.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef VERSION_H -#define VERSION_H - -#define VERSION_STR "0.5.10" - -#endif /* VERSION_H */ diff --git a/contrib/hostapd/vlan_init.c b/contrib/hostapd/vlan_init.c deleted file mode 100644 index d546c74afdc6..000000000000 --- a/contrib/hostapd/vlan_init.c +++ /dev/null @@ -1,835 +0,0 @@ -/* - * hostapd / VLAN initialization - * Copyright 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. - */ - -#include "includes.h" - -#include "hostapd.h" -#include "driver.h" -#include "vlan_init.h" - - -#ifdef CONFIG_FULL_DYNAMIC_VLAN - -#include <net/if.h> -#include <sys/ioctl.h> -#include <linux/sockios.h> -#include <linux/if_vlan.h> -typedef __uint64_t __u64; -typedef __uint32_t __u32; -typedef __int32_t __s32; -typedef __uint16_t __u16; -typedef __int16_t __s16; -typedef __uint8_t __u8; -#include <linux/if_bridge.h> - -#include "priv_netlink.h" -#include "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) { - perror("socket[AF_INET,SOCK_STREAM]"); - return -1; - } - - memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_name, if_name, IFNAMSIZ); - - if (ioctl(fd, SIOCGIFFLAGS, &ifr) != 0) { - perror("ioctl[SIOCGIFFLAGS]"); - close(fd); - return -1; - } - - if (up) - ifr.ifr_flags |= IFF_UP; - else - ifr.ifr_flags &= ~IFF_UP; - - if (ioctl(fd, SIOCSIFFLAGS, &ifr) != 0) { - perror("ioctl[SIOCSIFFLAGS]"); - close(fd); - return -1; - } - - close(fd); - return 0; -} - - -static int ifconfig_up(const char *if_name) -{ - return ifconfig_helper(if_name, 1); -} - - -static int ifconfig_down(const char *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; - - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("socket[AF_INET,SOCK_STREAM]"); - return -1; - } - - if_index = if_nametoindex(if_name); - - if (if_index == 0) { - printf("Failure determining interface index for '%s'\n", - if_name); - close(fd); - return -1; - } - - args[0] = BRCTL_DEL_IF; - args[1] = if_index; - - strncpy(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. */ - perror("ioctl[SIOCDEVPRIVATE,BRCTL_DEL_IF]"); - 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; - - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("socket[AF_INET,SOCK_STREAM]"); - return -1; - } - - if_index = if_nametoindex(if_name); - - if (if_index == 0) { - printf("Failure determining interface index for '%s'\n", - if_name); - close(fd); - return -1; - } - - args[0] = BRCTL_ADD_IF; - args[1] = if_index; - - strncpy(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; - } - - perror("ioctl[SIOCDEVPRIVATE,BRCTL_ADD_IF]"); - close(fd); - return -1; - } - - close(fd); - return 0; -} - - -static int br_delbr(const char *br_name) -{ - int fd; - unsigned long arg[2]; - - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("socket[AF_INET,SOCK_STREAM]"); - 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. */ - perror("ioctl[BRCTL_DEL_BRIDGE]"); - 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[2]; - - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("socket[AF_INET,SOCK_STREAM]"); - 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 { - perror("ioctl[BRCTL_ADD_BRIDGE]"); - close(fd); - return -1; - } - } - - 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) { - perror("socket[AF_INET,SOCK_STREAM]"); - return -1; - } - - arg[0] = BRCTL_GET_PORT_LIST; - arg[1] = (unsigned long) ifindices; - arg[2] = MAX_BR_PORTS; - arg[3] = 0; - - memset(ifindices, 0, sizeof(ifindices)); - strncpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name)); - ifr.ifr_data = (__caddr_t) arg; - - if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) { - perror("ioctl[SIOCDEVPRIVATE,BRCTL_GET_PORT_LIST]"); - 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; - - if ((strlen(if_name) + 1) > sizeof(if_request.device1)) { - fprintf(stderr, "Interface name to long.\n"); - return -1; - } - - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("socket[AF_INET,SOCK_STREAM]"); - return -1; - } - - memset(&if_request, 0, sizeof(if_request)); - - strcpy(if_request.device1, if_name); - if_request.cmd = DEL_VLAN_CMD; - - if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) { - perror("ioctl[SIOCSIFVLAN,DEL_VLAN_CMD]"); - 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; - - ifconfig_up(if_name); - - if ((strlen(if_name) + 1) > sizeof(if_request.device1)) { - fprintf(stderr, "Interface name to long.\n"); - return -1; - } - - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("socket[AF_INET,SOCK_STREAM]"); - return -1; - } - - memset(&if_request, 0, sizeof(if_request)); - - /* Determine if a suitable vlan device already exists. */ - - 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 - && strncmp(if_request.u.device2, if_name, - sizeof(if_request.u.device2)) == 0) { - close(fd); - return 1; - } - } - } - - /* A suitable vlan device does not already exist, add one. */ - - memset(&if_request, 0, sizeof(if_request)); - strcpy(if_request.device1, if_name); - if_request.u.VID = vid; - if_request.cmd = ADD_VLAN_CMD; - - if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) { - perror("ioctl[SIOCSIFVLAN,ADD_VLAN_CMD]"); - 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; - - if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("socket[AF_INET,SOCK_STREAM]"); - return -1; - } - - 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) { - perror("ioctl[SIOCSIFVLAN,SET_VLAN_NAME_TYPE_CMD]"); - 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; - - while (vlan) { - if (strcmp(ifname, vlan->ifname) == 0) { - - 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; - - 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; - int numports; - - first = prev = vlan; - - while (vlan) { - if (strcmp(ifname, vlan->ifname) == 0) { - snprintf(br_name, sizeof(br_name), "brvlan%d", - vlan->vlan_id); - - if (tagged_interface) { - snprintf(vlan_ifname, sizeof(vlan_ifname), - "vlan%d", vlan->vlan_id); - - numports = br_getnumports(br_name); - if (numports == 1) { - br_delif(br_name, vlan_ifname); - - vlan_rem(vlan_ifname); - - ifconfig_down(br_name); - br_delbr(br_name); - } - } - - if (vlan == first) { - hapd->conf->vlan = vlan->next; - } else { - prev->next = vlan->next; - } - 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; - - memset(ifname, 0, sizeof(ifname)); - - if ((size_t) n > sizeof(ifname)) - n = sizeof(ifname); - 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) - perror("recvfrom(netlink)"); - 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) { - printf("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) { - printf("%d extra bytes in the end of netlink message", - left); - } -} - - -static struct full_dynamic_vlan * -full_dynamic_vlan_init(struct hostapd_data *hapd) -{ - struct sockaddr_nl local; - struct full_dynamic_vlan *priv; - - priv = malloc(sizeof(*priv)); - - if (priv == NULL) - return NULL; - - memset(priv, 0, sizeof(*priv)); - - vlan_set_name_type(VLAN_NAME_TYPE_PLUS_VID_NO_PAD); - - priv->s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); - if (priv->s < 0) { - perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)"); - free(priv); - return NULL; - } - - 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) { - perror("bind(netlink)"); - close(priv->s); - free(priv); - return NULL; - } - - if (eloop_register_read_sock(priv->s, vlan_event_receive, hapd, NULL)) - { - close(priv->s); - 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); - 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_set_encryption(dyn_vlan, hapd, "WEP", NULL, - i, mssid->wep.key[i], - mssid->wep.len[i], - i == mssid->wep.idx)) { - printf("VLAN: Could not set WEP encryption for " - "dynamic VLAN.\n"); - 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 && - hostapd_if_add(hapd, HOSTAPD_IF_VLAN, vlan->ifname, NULL)) - { - if (errno != EEXIST) { - printf("Could not add VLAN iface: %s: %s\n", - vlan->ifname, strerror(errno)); - return -1; - } - } - - 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_if_remove(hapd, HOSTAPD_IF_VLAN, vlan->ifname, - NULL)) { - printf("Could not remove VLAN iface: %s: %s\n", - 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) -{ - if (vlan_dynamic_add(hapd, hapd->conf->vlan)) - return -1; - -#ifdef CONFIG_FULL_DYNAMIC_VLAN - hapd->full_dynamic_vlan = full_dynamic_vlan_init(hapd); -#endif /* CONFIG_FULL_DYNAMIC_VLAN */ - - 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 */ -} - - -int vlan_reconfig(struct hostapd_data *hapd, struct hostapd_config *oldconf, - struct hostapd_bss_config *oldbss) -{ - vlan_dynamic_remove(hapd, oldbss->vlan); - if (vlan_dynamic_add(hapd, hapd->conf->vlan)) - return -1; - - return 0; -} - - -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; - - ifname = strdup(vlan->ifname); - if (ifname == NULL) - return NULL; - pos = strchr(ifname, '#'); - if (pos == NULL) { - free(ifname); - return NULL; - } - *pos++ = '\0'; - - n = malloc(sizeof(*n)); - if (n == NULL) { - free(ifname); - return NULL; - } - - memset(n, 0, sizeof(*n)); - n->vlan_id = vlan_id; - n->dynamic_vlan = 1; - - snprintf(n->ifname, sizeof(n->ifname), "%s%d%s", ifname, vlan_id, pos); - free(ifname); - - if (hostapd_if_add(hapd, HOSTAPD_IF_VLAN, n->ifname, NULL)) { - free(n); - return NULL; - } - - n->next = hapd->conf->vlan; - hapd->conf->vlan = n; - - 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; - - 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_if_remove(hapd, HOSTAPD_IF_VLAN, vlan->ifname, NULL); - - return 0; -} diff --git a/contrib/hostapd/vlan_init.h b/contrib/hostapd/vlan_init.h deleted file mode 100644 index cf55ac246220..000000000000 --- a/contrib/hostapd/vlan_init.h +++ /dev/null @@ -1,31 +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 - -int vlan_init(struct hostapd_data *hapd); -void vlan_deinit(struct hostapd_data *hapd); -int vlan_reconfig(struct hostapd_data *hapd, struct hostapd_config *oldconf, - struct hostapd_bss_config *oldbss); -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); - -#endif /* VLAN_INIT_H */ diff --git a/contrib/hostapd/wired.conf b/contrib/hostapd/wired.conf deleted file mode 100644 index 956f8c53c540..000000000000 --- a/contrib/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/contrib/hostapd/wme.c b/contrib/hostapd/wme.c deleted file mode 100644 index 8be740f7e468..000000000000 --- a/contrib/hostapd/wme.c +++ /dev/null @@ -1,260 +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. - */ - -#include "includes.h" - -#include "hostapd.h" -#include "ieee802_11.h" -#include "wme.h" -#include "sta_info.h" -#include "driver.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 WME stations are receiving a certain group */ - - -static u8 wme_oui[3] = { 0x00, 0x50, 0xf2 }; - - -/* Add WME Parameter Element to Beacon and Probe Response frames. */ -u8 * hostapd_eid_wme(struct hostapd_data *hapd, u8 *eid) -{ - u8 *pos = eid; - struct wme_parameter_element *wme = - (struct wme_parameter_element *) (pos + 2); - int e; - - if (!hapd->conf->wme_enabled) - return eid; - eid[0] = WLAN_EID_VENDOR_SPECIFIC; - wme->oui[0] = 0x00; - wme->oui[1] = 0x50; - wme->oui[2] = 0xf2; - wme->oui_type = WME_OUI_TYPE; - wme->oui_subtype = WME_OUI_SUBTYPE_PARAMETER_ELEMENT; - wme->version = WME_VERSION; - wme->acInfo = hapd->parameter_set_count & 0xf; - - /* fill in a parameter set record for each AC */ - for (e = 0; e < 4; e++) { - struct wme_ac_parameter *ac = &wme->ac[e]; - struct hostapd_wme_ac_params *acp = - &hapd->iconf->wme_ac_params[e]; - - ac->aifsn = acp->aifs; - ac->acm = acp->admission_control_mandatory; - ac->aci = e; - ac->reserved = 0; - ac->eCWmin = acp->cwmin; - ac->eCWmax = acp->cwmax; - ac->txopLimit = host_to_le16(acp->txopLimit); - } - - pos = (u8 *) (wme + 1); - eid[1] = pos - eid - 2; /* element length */ - - return pos; -} - - -/* This function is called when a station sends an association request with - * WME info element. The function returns zero on success or non-zero on any - * error in WME element. eid does not include Element ID and Length octets. */ -int hostapd_eid_wme_valid(struct hostapd_data *hapd, u8 *eid, size_t len) -{ - struct wme_information_element *wme; - - wpa_hexdump(MSG_MSGDUMP, "WME IE", eid, len); - - if (len < sizeof(struct wme_information_element)) { - printf("Too short WME IE (len=%lu)\n", (unsigned long) len); - return -1; - } - - wme = (struct wme_information_element *) eid; - HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Validating WME IE: OUI " - "%02x:%02x:%02x OUI type %d OUI sub-type %d " - "version %d\n", - wme->oui[0], wme->oui[1], wme->oui[2], wme->oui_type, - wme->oui_subtype, wme->version); - if (memcmp(wme->oui, wme_oui, sizeof(wme_oui)) != 0 || - wme->oui_type != WME_OUI_TYPE || - wme->oui_subtype != WME_OUI_SUBTYPE_INFORMATION_ELEMENT || - wme->version != WME_VERSION) { - printf("Unsupported WME IE OUI/Type/Subtype/Version\n"); - return -1; - } - - return 0; -} - - -/* This function is called when a station sends an ACK frame for an AssocResp - * frame (status=success) and the matching AssocReq contained a WME element. - */ -int hostapd_wme_sta_config(struct hostapd_data *hapd, struct sta_info *sta) -{ - /* update kernel STA data for WME related items (WLAN_STA_WPA flag) */ - if (sta->flags & WLAN_STA_WME) - hostapd_sta_set_flags(hapd, sta->addr, WLAN_STA_WME, ~0); - else - hostapd_sta_set_flags(hapd, sta->addr, 0, ~WLAN_STA_WME); - - return 0; -} - - -static void wme_send_action(struct hostapd_data *hapd, const u8 *addr, - const struct wme_tspec_info_element *tspec, - u8 action_code, u8 dialogue_token, u8 status_code) -{ - u8 buf[256]; - struct ieee80211_mgmt *m = (struct ieee80211_mgmt *) buf; - struct wme_tspec_info_element *t = - (struct wme_tspec_info_element *) - m->u.action.u.wme_action.variable; - int len; - - hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "action response - reason %d", status_code); - memset(buf, 0, sizeof(buf)); - m->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_ACTION); - memcpy(m->da, addr, ETH_ALEN); - memcpy(m->sa, hapd->own_addr, ETH_ALEN); - memcpy(m->bssid, hapd->own_addr, ETH_ALEN); - m->u.action.category = WME_ACTION_CATEGORY; - m->u.action.u.wme_action.action_code = action_code; - m->u.action.u.wme_action.dialog_token = dialogue_token; - m->u.action.u.wme_action.status_code = status_code; - memcpy(t, tspec, sizeof(struct wme_tspec_info_element)); - len = ((u8 *) (t + 1)) - buf; - - if (hostapd_send_mgmt_frame(hapd, m, len, 0) < 0) - perror("wme_send_action: send"); -} - - -/* given frame data payload size in bytes, and data_rate in bits per second - * returns time to complete frame exchange */ -/* FIX: should not use floating point types */ -static double wme_frame_exchange_time(int bytes, int data_rate, int encryption, - int cts_protection) -{ - /* TODO: account for MAC/PHY headers correctly */ - /* TODO: account for encryption headers */ - /* TODO: account for WDS headers */ - /* TODO: account for CTS protection */ - /* TODO: account for SIFS + ACK at minimum PHY rate */ - return (bytes + 400) * 8.0 / data_rate; -} - - -static void wme_setup_request(struct hostapd_data *hapd, - struct ieee80211_mgmt *mgmt, - struct wme_tspec_info_element *tspec, size_t len) -{ - /* FIX: should not use floating point types */ - double medium_time, pps; - - /* TODO: account for airtime and answer no to tspec setup requests - * when none left!! */ - - pps = (tspec->mean_data_rate / 8.0) / tspec->nominal_msdu_size; - medium_time = (tspec->surplus_bandwidth_allowance / 8) * pps * - wme_frame_exchange_time(tspec->nominal_msdu_size, - tspec->minimum_phy_rate, 0, 0); - tspec->medium_time = medium_time * 1000000.0 / 32.0; - - wme_send_action(hapd, mgmt->sa, tspec, WME_ACTION_CODE_SETUP_RESPONSE, - mgmt->u.action.u.wme_action.dialog_token, - WME_SETUP_RESPONSE_STATUS_ADMISSION_ACCEPTED); -} - - -void hostapd_wme_action(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt, - size_t len) -{ - int action_code; - int left = len - IEEE80211_HDRLEN - 4; - u8 *pos = ((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_WME)) != - (WLAN_STA_ASSOC | WLAN_STA_WME)) { - hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "wme action received is not from associated wme" - " station"); - /* TODO: respond with action frame refused status code */ - return; - } - - /* extract the tspec info element */ - if (ieee802_11_parse_elems(hapd, pos, left, &elems, 1) == ParseFailed) - { - hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "hostapd_wme_action - could not parse wme " - "action"); - /* TODO: respond with action frame invalid parameters status - * code */ - return; - } - - if (!elems.wme_tspec || - elems.wme_tspec_len != (sizeof(struct wme_tspec_info_element) - 2)) - { - hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "hostapd_wme_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.wme_action.action_code; - switch (action_code) { - case WME_ACTION_CODE_SETUP_REQUEST: - wme_setup_request(hapd, mgmt, (struct wme_tspec_info_element *) - elems.wme_tspec, len); - return; -#if 0 - /* TODO: needed for client implementation */ - case WME_ACTION_CODE_SETUP_RESPONSE: - wme_setup_request(hapd, mgmt, len); - return; - /* TODO: handle station teardown requests */ - case WME_ACTION_CODE_TEARDOWN: - wme_teardown(hapd, mgmt, len); - return; -#endif - } - - hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "hostapd_wme_action - unknown action code %d", - action_code); -} diff --git a/contrib/hostapd/wme.h b/contrib/hostapd/wme.h deleted file mode 100644 index 8c208832e525..000000000000 --- a/contrib/hostapd/wme.h +++ /dev/null @@ -1,146 +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 - -#ifdef __linux__ -#include <endian.h> -#endif /* __linux__ */ - -#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) -#include <sys/types.h> -#include <sys/endian.h> -#endif /* defined(__FreeBSD__) || defined(__NetBSD__) || - * defined(__DragonFly__) */ - -#define WME_OUI_TYPE 2 -#define WME_OUI_SUBTYPE_INFORMATION_ELEMENT 0 -#define WME_OUI_SUBTYPE_PARAMETER_ELEMENT 1 -#define WME_OUI_SUBTYPE_TSPEC_ELEMENT 2 -#define WME_VERSION 1 - -#define WME_ACTION_CATEGORY 17 -#define WME_ACTION_CODE_SETUP_REQUEST 0 -#define WME_ACTION_CODE_SETUP_RESPONSE 1 -#define WME_ACTION_CODE_TEARDOWN 2 - -#define WME_SETUP_RESPONSE_STATUS_ADMISSION_ACCEPTED 0 -#define WME_SETUP_RESPONSE_STATUS_INVALID_PARAMETERS 1 -#define WME_SETUP_RESPONSE_STATUS_REFUSED 3 - -#define WME_TSPEC_DIRECTION_UPLINK 0 -#define WME_TSPEC_DIRECTION_DOWNLINK 1 -#define WME_TSPEC_DIRECTION_BI_DIRECTIONAL 3 - -extern inline u16 tsinfo(int tag1d, int contention_based, int direction) -{ - return (tag1d << 11) | (contention_based << 7) | (direction << 5) | - (tag1d << 1); -} - - -struct wme_information_element { - /* required fields for WME version 1 */ - u8 oui[3]; - u8 oui_type; - u8 oui_subtype; - u8 version; - u8 acInfo; - -} __attribute__ ((packed)); - -struct wme_ac_parameter { -#if __BYTE_ORDER == __LITTLE_ENDIAN - /* byte 1 */ - u8 aifsn:4, - acm:1, - aci:2, - reserved:1; - - /* byte 2 */ - u8 eCWmin:4, - eCWmax:4; -#elif __BYTE_ORDER == __BIG_ENDIAN - /* byte 1 */ - u8 reserved:1, - aci:2, - acm:1, - aifsn:4; - - /* byte 2 */ - u8 eCWmax:4, - eCWmin:4; -#else -#error "Please fix <endian.h>" -#endif - - /* bytes 3 & 4 */ - u16 txopLimit; -} __attribute__ ((packed)); - -struct wme_parameter_element { - /* required fields for WME version 1 */ - u8 oui[3]; - u8 oui_type; - u8 oui_subtype; - u8 version; - u8 acInfo; - u8 reserved; - struct wme_ac_parameter ac[4]; - -} __attribute__ ((packed)); - -struct wme_tspec_info_element { - u8 eid; - u8 length; - u8 oui[3]; - u8 oui_type; - u8 oui_subtype; - u8 version; - u16 ts_info; - u16 nominal_msdu_size; - u16 maximum_msdu_size; - u32 minimum_service_interval; - u32 maximum_service_interval; - u32 inactivity_interval; - u32 start_time; - u32 minimum_data_rate; - u32 mean_data_rate; - u32 maximum_burst_size; - u32 minimum_phy_rate; - u32 peak_data_rate; - u32 delay_bound; - u16 surplus_bandwidth_allowance; - u16 medium_time; -} __attribute__ ((packed)); - - -/* Access Categories */ -enum { - WME_AC_BK = 1, - WME_AC_BE = 0, - WME_AC_VI = 2, - WME_AC_VO = 3 -}; - - -u8 * hostapd_eid_wme(struct hostapd_data *hapd, u8 *eid); -int hostapd_eid_wme_valid(struct hostapd_data *hapd, u8 *eid, size_t len); -int hostapd_wme_sta_config(struct hostapd_data *hapd, struct sta_info *sta); -void hostapd_wme_action(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt, - size_t len); - -#endif /* WME_H */ diff --git a/contrib/hostapd/wpa.c b/contrib/hostapd/wpa.c deleted file mode 100644 index 25ca57f78f4e..000000000000 --- a/contrib/hostapd/wpa.c +++ /dev/null @@ -1,3783 +0,0 @@ -/* - * hostapd - IEEE 802.11i-2004 / WPA Authenticator - * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * $FreeBSD$ - */ - -#include "includes.h" - -#ifndef CONFIG_NATIVE_WINDOWS - -#include "hostapd.h" -#include "eapol_sm.h" -#include "wpa.h" -#include "wme.h" -#include "sha1.h" -#include "md5.h" -#include "rc4.h" -#include "aes_wrap.h" -#include "crypto.h" -#include "eloop.h" -#include "ieee802_11.h" -#include "pmksa_cache.h" -#include "state_machine.h" - -#define STATE_MACHINE_DATA struct wpa_state_machine -#define STATE_MACHINE_DEBUG_PREFIX "WPA" -#define STATE_MACHINE_ADDR sm->addr - - -#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 - - -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[WPA_PMK_LEN]; - struct wpa_ptk PTK; - Boolean PTK_valid; - Boolean pairwise_set; - int keycount; - Boolean Pair; - u8 key_replay_counter[WPA_REPLAY_COUNTER_LEN]; - Boolean key_replay_counter_valid; - Boolean PInitAKeys; /* WPA only, not in IEEE 802.11i */ - Boolean PTKRequest; /* not in IEEE 802.11i state machine */ - Boolean has_GTK; - - 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; - - 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; -}; - - -/* 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; -#ifdef CONFIG_IEEE80211W - u8 DGTK[WPA_DGTK_LEN]; - u8 IGTK[2][WPA_IGTK_LEN]; -#endif /* CONFIG_IEEE80211W */ -}; - - -/* per authenticator data */ -struct wpa_authenticator { - struct wpa_group *group; - - unsigned int dot11RSNAStatsTKIPRemoteMICFailures; - u8 dot11RSNAAuthenticationSuiteSelected[4]; - u8 dot11RSNAPairwiseCipherSelected[4]; - u8 dot11RSNAGroupCipherSelected[4]; - u8 dot11RSNAPMKIDUsed[PMKID_LEN]; - u8 dot11RSNAAuthenticationSuiteRequested[4]; /* FIX: update */ - u8 dot11RSNAPairwiseCipherRequested[4]; /* FIX: update */ - u8 dot11RSNAGroupCipherRequested[4]; /* 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; -}; - - -static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx); -static void 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 int wpa_stsl_remove(struct wpa_authenticator *wpa_auth, - struct wpa_stsl_negotiation *neg); -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 force_version); - -/* Default timeouts are 100 ms, but this seems to be a bit too fast for most - * WPA Supplicants, so use a bit longer timeout. */ -static const u32 dot11RSNAConfigGroupUpdateTimeOut = 1000; /* ms */ -static const u32 dot11RSNAConfigGroupUpdateCount = 3; -static const u32 dot11RSNAConfigPairwiseUpdateTimeOut = 1000; /* ms */ -static const u32 dot11RSNAConfigPairwiseUpdateCount = 3; - -/* TODO: make these configurable */ -static const int dot11RSNAConfigPMKLifetime = 43200; -static const int dot11RSNAConfigPMKReauthThreshold = 70; -static const int dot11RSNAConfigSATimeout = 60; - - -static const int WPA_SELECTOR_LEN = 4; -static const u8 WPA_OUI_TYPE[] = { 0x00, 0x50, 0xf2, 1 }; -static const u16 WPA_VERSION = 1; -static const u8 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X[] = { 0x00, 0x50, 0xf2, 1 }; -static const u8 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X[] = { 0x00, 0x50, 0xf2, 2 }; -static const u8 WPA_CIPHER_SUITE_NONE[] = { 0x00, 0x50, 0xf2, 0 }; -static const u8 WPA_CIPHER_SUITE_WEP40[] = { 0x00, 0x50, 0xf2, 1 }; -static const u8 WPA_CIPHER_SUITE_TKIP[] = { 0x00, 0x50, 0xf2, 2 }; -static const u8 WPA_CIPHER_SUITE_WRAP[] = { 0x00, 0x50, 0xf2, 3 }; -static const u8 WPA_CIPHER_SUITE_CCMP[] = { 0x00, 0x50, 0xf2, 4 }; -static const u8 WPA_CIPHER_SUITE_WEP104[] = { 0x00, 0x50, 0xf2, 5 }; -#ifdef CONFIG_IEEE80211W -static const u8 RSN_CIPHER_SUITE_AES_128_CMAC[] = { 0x00, 0x0f, 0xac, 6 }; -#endif /* CONFIG_IEEE80211W */ - -static const int RSN_SELECTOR_LEN = 4; -static const u16 RSN_VERSION = 1; -static const u8 RSN_AUTH_KEY_MGMT_UNSPEC_802_1X[] = { 0x00, 0x0f, 0xac, 1 }; -static const u8 RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X[] = { 0x00, 0x0f, 0xac, 2 }; -static const u8 RSN_CIPHER_SUITE_NONE[] = { 0x00, 0x0f, 0xac, 0 }; -static const u8 RSN_CIPHER_SUITE_WEP40[] = { 0x00, 0x0f, 0xac, 1 }; -static const u8 RSN_CIPHER_SUITE_TKIP[] = { 0x00, 0x0f, 0xac, 2 }; -static const u8 RSN_CIPHER_SUITE_WRAP[] = { 0x00, 0x0f, 0xac, 3 }; -static const u8 RSN_CIPHER_SUITE_CCMP[] = { 0x00, 0x0f, 0xac, 4 }; -static const u8 RSN_CIPHER_SUITE_WEP104[] = { 0x00, 0x0f, 0xac, 5 }; - -/* EAPOL-Key Key Data Encapsulation - * GroupKey and PeerKey require encryption, otherwise, encryption is optional. - */ -static const u8 RSN_KEY_DATA_GROUPKEY[] = { 0x00, 0x0f, 0xac, 1 }; -#if 0 -static const u8 RSN_KEY_DATA_STAKEY[] = { 0x00, 0x0f, 0xac, 2 }; -#endif -static const u8 RSN_KEY_DATA_MAC_ADDR[] = { 0x00, 0x0f, 0xac, 3 }; -static const u8 RSN_KEY_DATA_PMKID[] = { 0x00, 0x0f, 0xac, 4 }; -#ifdef CONFIG_PEERKEY -static const u8 RSN_KEY_DATA_SMK[] = { 0x00, 0x0f, 0xac, 5 }; -static const u8 RSN_KEY_DATA_NONCE[] = { 0x00, 0x0f, 0xac, 6 }; -static const u8 RSN_KEY_DATA_LIFETIME[] = { 0x00, 0x0f, 0xac, 7 }; -static const u8 RSN_KEY_DATA_ERROR[] = { 0x00, 0x0f, 0xac, 8 }; -#endif /* CONFIG_PEERKEY */ -#ifdef CONFIG_IEEE80211W -/* FIX: IEEE 802.11w/D1.0 is using subtypes 5 and 6 for these, but they were - * already taken by 802.11ma (PeerKey). Need to update the values here once - * IEEE 802.11w fixes these. */ -static const u8 RSN_KEY_DATA_DHV[] = { 0x00, 0x0f, 0xac, 9 }; -static const u8 RSN_KEY_DATA_IGTK[] = { 0x00, 0x0f, 0xac, 10 }; -#endif /* CONFIG_IEEE80211W */ - -#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 */ - -#define GENERIC_INFO_ELEM 0xdd -#define RSN_INFO_ELEM 0x30 - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -/* 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[3]; - u8 oui_type; - u16 version; -} STRUCT_PACKED; - - -/* 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; - u16 version; -} STRUCT_PACKED; - - -struct rsn_error_kde { - u16 mui; - u16 error_type; -} STRUCT_PACKED; - - -#ifdef CONFIG_IEEE80211W -struct wpa_dhv_kde { - u8 dhv[WPA_DHV_LEN]; -} STRUCT_PACKED; - -struct wpa_igtk_kde { - u8 keyid[2]; - u8 pn[6]; - u8 igtk[WPA_IGTK_LEN]; -} STRUCT_PACKED; -#endif /* CONFIG_IEEE80211W */ - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - - -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_pmk(struct wpa_authenticator *wpa_auth, - const u8 *addr, u8 *pmk, size_t *len) -{ - if (wpa_auth->cb.get_pmk == NULL) - return -1; - return wpa_auth->cb.get_pmk(wpa_auth->cb.ctx, addr, pmk, len); -} - - -static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth, - int vlan_id, - const char *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_get_seqnum_igtk(struct wpa_authenticator *wpa_auth, - const u8 *addr, int idx, u8 *seq) -{ - if (wpa_auth->cb.get_seqnum_igtk == NULL) - return -1; - return wpa_auth->cb.get_seqnum_igtk(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); -} - - -static inline 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); -} - - -static 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); -} - - -static 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 = strlen(fmt) + 100; - format = 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); - - free(format); -} - - -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_GENERIC; - memcpy(&hdr->oui, WPA_OUI_TYPE, WPA_SELECTOR_LEN); - hdr->version = host_to_le16(WPA_VERSION); - pos = (u8 *) (hdr + 1); - - if (conf->wpa_group == WPA_CIPHER_CCMP) { - memcpy(pos, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN); - } else if (conf->wpa_group == WPA_CIPHER_TKIP) { - memcpy(pos, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN); - } else if (conf->wpa_group == WPA_CIPHER_WEP104) { - memcpy(pos, WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN); - } else if (conf->wpa_group == WPA_CIPHER_WEP40) { - memcpy(pos, WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN); - } 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) { - memcpy(pos, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN); - pos += WPA_SELECTOR_LEN; - num_suites++; - } - if (conf->wpa_pairwise & WPA_CIPHER_TKIP) { - memcpy(pos, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN); - pos += WPA_SELECTOR_LEN; - num_suites++; - } - if (conf->wpa_pairwise & WPA_CIPHER_NONE) { - memcpy(pos, WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN); - pos += WPA_SELECTOR_LEN; - num_suites++; - } - - if (num_suites == 0) { - wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).", - conf->wpa_pairwise); - return -1; - } - *count++ = num_suites & 0xff; - *count = (num_suites >> 8) & 0xff; - - num_suites = 0; - count = pos; - pos += 2; - - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) { - memcpy(pos, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X, WPA_SELECTOR_LEN); - pos += WPA_SELECTOR_LEN; - num_suites++; - } - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) { - memcpy(pos, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X, - WPA_SELECTOR_LEN); - 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; - } - *count++ = num_suites & 0xff; - *count = (num_suites >> 8) & 0xff; - - /* WPA Capabilities; use defaults, so no need to include it */ - - hdr->len = (pos - buf) - 2; - - return pos - buf; -} - - -static int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len) -{ - 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; - pos = (u8 *) &hdr->version; - *pos++ = RSN_VERSION & 0xff; - *pos++ = RSN_VERSION >> 8; - pos = (u8 *) (hdr + 1); - - if (conf->wpa_group == WPA_CIPHER_CCMP) { - memcpy(pos, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN); - } else if (conf->wpa_group == WPA_CIPHER_TKIP) { - memcpy(pos, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN); - } else if (conf->wpa_group == WPA_CIPHER_WEP104) { - memcpy(pos, RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN); - } else if (conf->wpa_group == WPA_CIPHER_WEP40) { - memcpy(pos, RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN); - } 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; - - if (conf->wpa_pairwise & WPA_CIPHER_CCMP) { - memcpy(pos, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN); - pos += RSN_SELECTOR_LEN; - num_suites++; - } - if (conf->wpa_pairwise & WPA_CIPHER_TKIP) { - memcpy(pos, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN); - pos += RSN_SELECTOR_LEN; - num_suites++; - } - if (conf->wpa_pairwise & WPA_CIPHER_NONE) { - memcpy(pos, RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN); - pos += RSN_SELECTOR_LEN; - num_suites++; - } - - if (num_suites == 0) { - wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).", - conf->wpa_pairwise); - return -1; - } - *count++ = num_suites & 0xff; - *count = (num_suites >> 8) & 0xff; - - num_suites = 0; - count = pos; - pos += 2; - - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) { - memcpy(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X, RSN_SELECTOR_LEN); - pos += RSN_SELECTOR_LEN; - num_suites++; - } - if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) { - memcpy(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X, - RSN_SELECTOR_LEN); - pos += RSN_SELECTOR_LEN; - num_suites++; - } - - if (num_suites == 0) { - wpa_printf(MSG_DEBUG, "Invalid key management type (%d).", - conf->wpa_key_mgmt); - return -1; - } - *count++ = num_suites & 0xff; - *count = (num_suites >> 8) & 0xff; - - /* RSN Capabilities */ - capab = 0; - if (conf->rsn_preauth) - capab |= WPA_CAPABILITY_PREAUTH; - if (conf->peerkey) - capab |= WPA_CAPABILITY_PEERKEY_ENABLED; - if (conf->wme_enabled) { - /* 4 PTKSA replay counters when using WME */ - capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2); - } -#ifdef CONFIG_IEEE80211W - if (conf->ieee80211w != WPA_NO_IEEE80211W) - capab |= WPA_CAPABILITY_MGMT_FRAME_PROTECTION; -#endif /* CONFIG_IEEE80211W */ - *pos++ = capab & 0xff; - *pos++ = capab >> 8; - -#ifdef CONFIG_IEEE80211W - if (conf->ieee80211w != WPA_NO_IEEE80211W) { - if (pos + 2 + 4 > buf + len) - return -1; - /* PMKID Count */ - WPA_PUT_LE16(pos, 0); - pos += 2; - - /* Management Group Cipher Suite */ - memcpy(pos, RSN_CIPHER_SUITE_AES_128_CMAC, RSN_SELECTOR_LEN); - pos += RSN_SELECTOR_LEN; - } -#endif /* CONFIG_IEEE80211W */ - - hdr->len = (pos - buf) - 2; - - return pos - buf; -} - - -static int wpa_gen_wpa_ie(struct wpa_authenticator *wpa_auth) -{ - u8 *pos, buf[100]; - int res; - - pos = buf; - - if (wpa_auth->conf.wpa & HOSTAPD_WPA_VERSION_WPA2) { - res = wpa_write_rsn_ie(&wpa_auth->conf, - pos, buf + sizeof(buf) - pos); - if (res < 0) - return res; - pos += res; - } - if (wpa_auth->conf.wpa & HOSTAPD_WPA_VERSION_WPA) { - res = wpa_write_wpa_ie(&wpa_auth->conf, - pos, buf + sizeof(buf) - pos); - if (res < 0) - return res; - pos += res; - } - - free(wpa_auth->wpa_ie); - wpa_auth->wpa_ie = malloc(pos - buf); - if (wpa_auth->wpa_ie == NULL) - return -1; - memcpy(wpa_auth->wpa_ie, buf, pos - buf); - wpa_auth->wpa_ie_len = pos - buf; - - return 0; -} - - -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 void wpa_rekey_gmk(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_authenticator *wpa_auth = eloop_ctx; - - if (hostapd_get_rand(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"); - } - - 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 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 struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth, - int vlan_id) -{ - struct wpa_group *group; - u8 buf[ETH_ALEN + 8 + sizeof(group)]; - u8 rkey[32]; - - group = wpa_zalloc(sizeof(struct wpa_group)); - if (group == NULL) - return NULL; - - group->GTKAuthenticator = TRUE; - group->vlan_id = vlan_id; - - switch (wpa_auth->conf.wpa_group) { - 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; - } - - /* Counter = PRF-256(Random number, "Init Counter", - * Local MAC Address || Time) - */ - memcpy(buf, wpa_auth->addr, ETH_ALEN); - wpa_get_ntp_timestamp(buf + ETH_ALEN); - memcpy(buf + ETH_ALEN + 8, &group, sizeof(group)); - if (hostapd_get_rand(rkey, sizeof(rkey)) || - hostapd_get_rand(group->GMK, WPA_GMK_LEN)) { - wpa_printf(MSG_ERROR, "Failed to get random data for WPA " - "initialization."); - free(group); - return NULL; - } - - sha1_prf(rkey, sizeof(rkey), "Init Counter", buf, sizeof(buf), - group->Counter, WPA_NONCE_LEN); - - 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 - * 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 = wpa_zalloc(sizeof(struct wpa_authenticator)); - if (wpa_auth == NULL) - return NULL; - memcpy(wpa_auth->addr, addr, ETH_ALEN); - memcpy(&wpa_auth->conf, conf, sizeof(*conf)); - memcpy(&wpa_auth->cb, cb, sizeof(*cb)); - - if (wpa_gen_wpa_ie(wpa_auth)) { - wpa_printf(MSG_ERROR, "Could not generate WPA IE."); - free(wpa_auth); - return NULL; - } - - wpa_auth->group = wpa_group_init(wpa_auth, 0); - if (wpa_auth->group == NULL) { - free(wpa_auth->wpa_ie); - free(wpa_auth); - return NULL; - } - - wpa_auth->pmksa = pmksa_cache_init(wpa_auth_pmksa_free_cb, wpa_auth); - if (wpa_auth->pmksa == NULL) { - wpa_printf(MSG_ERROR, "PMKSA cache initialization failed."); - free(wpa_auth->wpa_ie); - free(wpa_auth); - return NULL; - } - - 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); - - while (wpa_auth->stsl_negotiations) - wpa_stsl_remove(wpa_auth, wpa_auth->stsl_negotiations); - - pmksa_cache_deinit(wpa_auth->pmksa); - - free(wpa_auth->wpa_ie); - - group = wpa_auth->group; - while (group) { - prev = group; - group = group->next; - free(prev); - } - - 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) -{ - if (wpa_auth == NULL) - return 0; - - memcpy(&wpa_auth->conf, conf, sizeof(*conf)); - /* - * TODO: - * Disassociate stations if configuration changed - * Update WPA/RSN IE - */ - return 0; -} - - -static int wpa_selector_to_bitfield(u8 *s) -{ - if (memcmp(s, WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN) == 0) - return WPA_CIPHER_NONE; - if (memcmp(s, WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN) == 0) - return WPA_CIPHER_WEP40; - if (memcmp(s, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN) == 0) - return WPA_CIPHER_TKIP; - if (memcmp(s, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN) == 0) - return WPA_CIPHER_CCMP; - if (memcmp(s, WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN) == 0) - return WPA_CIPHER_WEP104; - return 0; -} - - -static int wpa_key_mgmt_to_bitfield(u8 *s) -{ - if (memcmp(s, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X, WPA_SELECTOR_LEN) == 0) - return WPA_KEY_MGMT_IEEE8021X; - if (memcmp(s, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X, WPA_SELECTOR_LEN) == - 0) - return WPA_KEY_MGMT_PSK; - return 0; -} - - -static int rsn_selector_to_bitfield(u8 *s) -{ - if (memcmp(s, RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN) == 0) - return WPA_CIPHER_NONE; - if (memcmp(s, RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN) == 0) - return WPA_CIPHER_WEP40; - if (memcmp(s, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN) == 0) - return WPA_CIPHER_TKIP; - if (memcmp(s, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN) == 0) - return WPA_CIPHER_CCMP; - if (memcmp(s, RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN) == 0) - return WPA_CIPHER_WEP104; -#ifdef CONFIG_IEEE80211W - if (memcmp(s, RSN_CIPHER_SUITE_AES_128_CMAC, RSN_SELECTOR_LEN) == 0) - return WPA_CIPHER_AES_128_CMAC; -#endif /* CONFIG_IEEE80211W */ - return 0; -} - - -static int rsn_key_mgmt_to_bitfield(u8 *s) -{ - if (memcmp(s, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X, RSN_SELECTOR_LEN) == 0) - return WPA_KEY_MGMT_IEEE8021X; - if (memcmp(s, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X, RSN_SELECTOR_LEN) == - 0) - return WPA_KEY_MGMT_PSK; - return 0; -} - - -static u8 * wpa_add_kde(u8 *pos, const u8 *kde, const u8 *data, - size_t data_len, const u8 *data2, size_t data2_len) -{ - *pos++ = GENERIC_INFO_ELEM; - *pos++ = RSN_SELECTOR_LEN + data_len + data2_len; - memcpy(pos, kde, RSN_SELECTOR_LEN); - pos += RSN_SELECTOR_LEN; - memcpy(pos, data, data_len); - pos += data_len; - if (data2) { - memcpy(pos, data2, data2_len); - pos += data2_len; - } - return pos; -} - - -struct wpa_ie_data { - int pairwise_cipher; - int group_cipher; - int key_mgmt; - int capabilities; - size_t num_pmkid; - u8 *pmkid; - int mgmt_group_cipher; -}; - - -static int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len, - struct wpa_ie_data *data) -{ - struct wpa_ie_hdr *hdr; - u8 *pos; - int left; - int i, count; - - memset(data, 0, sizeof(*data)); - data->pairwise_cipher = WPA_CIPHER_TKIP; - data->group_cipher = WPA_CIPHER_TKIP; - data->key_mgmt = WPA_KEY_MGMT_IEEE8021X; - data->mgmt_group_cipher = 0; - - if (wpa_ie_len < sizeof(struct wpa_ie_hdr)) - return -1; - - hdr = (struct wpa_ie_hdr *) wpa_ie; - - if (hdr->elem_id != WLAN_EID_GENERIC || - hdr->len != wpa_ie_len - 2 || - memcmp(&hdr->oui, WPA_OUI_TYPE, WPA_SELECTOR_LEN) != 0 || - le_to_host16(hdr->version) != WPA_VERSION) { - return -2; - } - - pos = (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) - return -3; - - if (left >= 2) { - data->pairwise_cipher = 0; - count = pos[0] | (pos[1] << 8); - pos += 2; - left -= 2; - if (count == 0 || left < count * WPA_SELECTOR_LEN) - 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) - return -5; - - if (left >= 2) { - data->key_mgmt = 0; - count = pos[0] | (pos[1] << 8); - pos += 2; - left -= 2; - if (count == 0 || left < count * WPA_SELECTOR_LEN) - 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) - return -7; - - if (left >= 2) { - data->capabilities = pos[0] | (pos[1] << 8); - pos += 2; - left -= 2; - } - - if (left > 0) { - return -8; - } - - return 0; -} - - -static int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, - struct wpa_ie_data *data) -{ - struct rsn_ie_hdr *hdr; - u8 *pos; - int left; - int i, count; - - memset(data, 0, sizeof(*data)); - data->pairwise_cipher = WPA_CIPHER_CCMP; - data->group_cipher = WPA_CIPHER_CCMP; - data->key_mgmt = WPA_KEY_MGMT_IEEE8021X; -#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 < sizeof(struct rsn_ie_hdr)) - return -1; - - hdr = (struct rsn_ie_hdr *) rsn_ie; - - if (hdr->elem_id != WLAN_EID_RSN || - hdr->len != rsn_ie_len - 2 || - le_to_host16(hdr->version) != RSN_VERSION) { - return -2; - } - - pos = (u8 *) (hdr + 1); - left = rsn_ie_len - sizeof(*hdr); - - if (left >= RSN_SELECTOR_LEN) { - data->group_cipher = rsn_selector_to_bitfield(pos); - pos += RSN_SELECTOR_LEN; - left -= RSN_SELECTOR_LEN; - } else if (left > 0) - return -3; - - if (left >= 2) { - data->pairwise_cipher = 0; - count = pos[0] | (pos[1] << 8); - pos += 2; - left -= 2; - if (count == 0 || left < count * RSN_SELECTOR_LEN) - return -4; - for (i = 0; i < count; i++) { - data->pairwise_cipher |= rsn_selector_to_bitfield(pos); - pos += RSN_SELECTOR_LEN; - left -= RSN_SELECTOR_LEN; - } - } else if (left == 1) - return -5; - - if (left >= 2) { - data->key_mgmt = 0; - count = pos[0] | (pos[1] << 8); - pos += 2; - left -= 2; - if (count == 0 || left < count * RSN_SELECTOR_LEN) - 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) - return -7; - - if (left >= 2) { - data->capabilities = pos[0] | (pos[1] << 8); - pos += 2; - left -= 2; - } - - if (left >= 2) { - data->num_pmkid = pos[0] | (pos[1] << 8); - pos += 2; - left -= 2; - if (left < (int) data->num_pmkid * PMKID_LEN) { - wpa_printf(MSG_DEBUG, "RSN: too short RSN IE for " - "PMKIDs (num=%lu, left=%d)", - (unsigned long) data->num_pmkid, left); - return -9; - } - 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, "RSN: Unsupported management " - "group cipher 0x%x", - data->mgmt_group_cipher); - return -10; - } - pos += RSN_SELECTOR_LEN; - left -= RSN_SELECTOR_LEN; - } -#endif /* CONFIG_IEEE80211W */ - - if (left > 0) { - return -8; - } - - 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) -{ - struct wpa_ie_data data; - int ciphers, key_mgmt, res, version; - const u8 *selector; - size_t i; - - 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 = HOSTAPD_WPA_VERSION_WPA2; - else - version = HOSTAPD_WPA_VERSION_WPA; - - if (version == HOSTAPD_WPA_VERSION_WPA2) { - res = wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, &data); - - selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X; - 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; - memcpy(wpa_auth->dot11RSNAAuthenticationSuiteSelected, - selector, RSN_SELECTOR_LEN); - - 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; - memcpy(wpa_auth->dot11RSNAPairwiseCipherSelected, - selector, RSN_SELECTOR_LEN); - - 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; - memcpy(wpa_auth->dot11RSNAGroupCipherSelected, - selector, RSN_SELECTOR_LEN); - } 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; - memcpy(wpa_auth->dot11RSNAAuthenticationSuiteSelected, - selector, WPA_SELECTOR_LEN); - - 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; - memcpy(wpa_auth->dot11RSNAPairwiseCipherSelected, - selector, WPA_SELECTOR_LEN); - - 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; - memcpy(wpa_auth->dot11RSNAGroupCipherSelected, - selector, WPA_SELECTOR_LEN); - } - 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 (key_mgmt & WPA_KEY_MGMT_IEEE8021X) - sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X; - else - sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK; - - ciphers = data.pairwise_cipher & wpa_auth->conf.wpa_pairwise; - if (!ciphers) { - wpa_printf(MSG_DEBUG, "Invalid WPA pairwise cipher (0x%x) " - "from " MACSTR, - data.pairwise_cipher, MAC2STR(sm->addr)); - return WPA_INVALID_PAIRWISE; - } - -#ifdef CONFIG_IEEE80211W - if (wpa_auth->conf.ieee80211w == WPA_IEEE80211W_REQUIRED) { - if (!(data.capabilities & - WPA_CAPABILITY_MGMT_FRAME_PROTECTION)) { - 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 == WPA_NO_IEEE80211W || - !(data.capabilities & WPA_CAPABILITY_MGMT_FRAME_PROTECTION)) - sm->mgmt_frame_prot = 0; - else - sm->mgmt_frame_prot = 1; -#endif /* CONFIG_IEEE80211W */ - - 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; - - 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_get(wpa_auth->pmksa, sm->addr, - &data.pmkid[i * PMKID_LEN]); - 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); - memcpy(wpa_auth->dot11RSNAPMKIDUsed, - sm->pmksa->pmkid, PMKID_LEN); - break; - } - } - - if (sm->wpa_ie == NULL || sm->wpa_ie_len < wpa_ie_len) { - free(sm->wpa_ie); - sm->wpa_ie = malloc(wpa_ie_len); - if (sm->wpa_ie == NULL) - return WPA_ALLOC_FAIL; - } - memcpy(sm->wpa_ie, wpa_ie, wpa_ie_len); - sm->wpa_ie_len = wpa_ie_len; - - return WPA_IE_OK; -} - - -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 */ -}; - - -/** - * 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 && - memcmp(pos + 2, WPA_OUI_TYPE, WPA_SELECTOR_LEN) == 0 && - 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 && - memcmp(pos + 2, RSN_KEY_DATA_PMKID, RSN_SELECTOR_LEN) == 0) { - ie->pmkid = pos + 2 + RSN_SELECTOR_LEN; - return 0; - } - - if (pos[1] > RSN_SELECTOR_LEN + 2 && - memcmp(pos + 2, RSN_KEY_DATA_GROUPKEY, RSN_SELECTOR_LEN) == 0) { - ie->gtk = pos + 2 + RSN_SELECTOR_LEN; - ie->gtk_len = pos[1] - RSN_SELECTOR_LEN; - return 0; - } - - if (pos[1] > RSN_SELECTOR_LEN + 2 && - memcmp(pos + 2, RSN_KEY_DATA_MAC_ADDR, RSN_SELECTOR_LEN) == 0) { - 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 && - memcmp(pos + 2, RSN_KEY_DATA_SMK, RSN_SELECTOR_LEN) == 0) { - ie->smk = pos + 2 + RSN_SELECTOR_LEN; - ie->smk_len = pos[1] - RSN_SELECTOR_LEN; - return 0; - } - - if (pos[1] > RSN_SELECTOR_LEN + 2 && - memcmp(pos + 2, RSN_KEY_DATA_NONCE, RSN_SELECTOR_LEN) == 0) { - ie->nonce = pos + 2 + RSN_SELECTOR_LEN; - ie->nonce_len = pos[1] - RSN_SELECTOR_LEN; - return 0; - } - - if (pos[1] > RSN_SELECTOR_LEN + 2 && - memcmp(pos + 2, RSN_KEY_DATA_LIFETIME, RSN_SELECTOR_LEN) == 0) { - ie->lifetime = pos + 2 + RSN_SELECTOR_LEN; - ie->lifetime_len = pos[1] - RSN_SELECTOR_LEN; - return 0; - } - - if (pos[1] > RSN_SELECTOR_LEN + 2 && - memcmp(pos + 2, RSN_KEY_DATA_ERROR, RSN_SELECTOR_LEN) == 0) { - ie->error = pos + 2 + RSN_SELECTOR_LEN; - ie->error_len = pos[1] - RSN_SELECTOR_LEN; - return 0; - } -#endif /* CONFIG_PEERKEY */ - - 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 - */ -static int wpa_parse_kde_ies(const u8 *buf, size_t len, - struct wpa_eapol_ie_parse *ie) -{ - const u8 *pos, *end; - int ret = 0; - - 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[0], pos[1]); - ret = -1; - break; - } - if (*pos == RSN_INFO_ELEM) { - ie->rsn_ie = pos; - ie->rsn_ie_len = pos[1] + 2; - } else if (*pos == GENERIC_INFO_ELEM) { - 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; -} - - -struct wpa_state_machine * -wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr) -{ - struct wpa_state_machine *sm; - - sm = wpa_zalloc(sizeof(struct wpa_state_machine)); - if (sm == NULL) - return NULL; - memcpy(sm->addr, addr, ETH_ALEN); - - sm->wpa_auth = wpa_auth; - sm->group = wpa_auth->group; - - return sm; -} - - -void 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; - - if (sm->started) { - memset(sm->key_replay_counter, 0, WPA_REPLAY_COUNTER_LEN); - sm->ReAuthenticationRequest = TRUE; - wpa_sm_step(sm); - return; - } - - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, - "start authentication"); - sm->started = 1; - - sm->Init = TRUE; - wpa_sm_step(sm); - sm->Init = FALSE; - sm->AuthenticationRequest = TRUE; - wpa_sm_step(sm); -} - - -static void wpa_free_sta_sm(struct wpa_state_machine *sm) -{ - free(sm->last_rx_eapol_key); - free(sm->wpa_ie); - 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); - eloop_cancel_timeout(wpa_sm_call_step, sm, NULL); - 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; -} - - -#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 (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)]; - size_t kde_len; - u8 *pos; - struct rsn_error_kde error; - - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, - "Sending SMK Error"); - - kde_len = 2 + RSN_SELECTOR_LEN + sizeof(struct rsn_error_kde); - pos = kde; - - if (peer) { - pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN, - NULL, 0); - kde_len += 2 + RSN_SELECTOR_LEN + ETH_ALEN; - } - - 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, kde_len, 0, 0, 0); -} - - -static 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), - ntohs(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 = malloc(buf_len); - if (buf == NULL) - return; - /* Initiator RSN IE */ - 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, buf_len, 0, 0, 0); - - 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 + WPA_PMK_LEN + WPA_NONCE_LEN + - 2 + RSN_SELECTOR_LEN + sizeof(lifetime); - pos = buf = 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, WPA_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, buf_len, 0, 1, 0); - - 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 + WPA_PMK_LEN + WPA_NONCE_LEN + - 2 + RSN_SELECTOR_LEN + sizeof(lifetime); - pos = buf = malloc(buf_len); - if (buf == NULL) - return; - - /* Peer RSN IE */ - 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, WPA_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, buf_len, 0, 1, 0); - - free(buf); -} - - -static 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), - ntohs(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 (hostapd_get_rand(smk, WPA_PMK_LEN)) { - wpa_printf(MSG_DEBUG, "RSN: Failed to generate SMK"); - return; - } - - /* SMK = PRF-256(Random number, "SMK Derivation", - * AA || Time || INonce || PNonce) - */ - memcpy(buf, wpa_auth->addr, ETH_ALEN); - pos = buf + ETH_ALEN; - wpa_get_ntp_timestamp(pos); - pos += 8; - memcpy(pos, kde.nonce, WPA_NONCE_LEN); - pos += WPA_NONCE_LEN; - memcpy(pos, key->key_nonce, WPA_NONCE_LEN); - sha1_prf(smk, WPA_PMK_LEN, "SMK Derivation", buf, sizeof(buf), - smk, WPA_PMK_LEN); - - wpa_hexdump_key(MSG_DEBUG, "RSN: SMK", smk, WPA_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. */ - memset(smk, 0, sizeof(*smk)); -} - - -static 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), - ntohs(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; - } - - 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); -} -#endif /* CONFIG_PEERKEY */ - - -static int wpa_stsl_remove(struct wpa_authenticator *wpa_auth, - struct wpa_stsl_negotiation *neg) -{ -#ifdef CONFIG_PEERKEY - 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); - free(pos); - return 0; - } - prev = pos; - pos = pos->next; - } -#endif /* CONFIG_PEERKEY */ - - return -1; -} - - -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; - - 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 = ntohs(key->key_info); - key_data_length = ntohs(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; - } - - /* 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"; - } - - if (key_info & WPA_KEY_INFO_REQUEST) { - if (sm->req_replay_counter_used && - 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) && - (!sm->key_replay_counter_valid || - memcmp(key->replay_counter, sm->key_replay_counter, - WPA_REPLAY_COUNTER_LEN) != 0)) { - wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key %s with unexpected " - "replay counter", msgtxt); - wpa_hexdump(MSG_DEBUG, "expected replay counter", - sm->key_replay_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; - } - if (sm->wpa_ie == NULL || - sm->wpa_ie_len != key_data_length || - memcmp(sm->wpa_ie, key + 1, key_data_length) != 0) { - 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", - (u8 *) (key + 1), key_data_length); - /* MLME-DEAUTHENTICATE.request */ - wpa_sta_disconnect(wpa_auth, sm->addr); - return; - } - 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); - } - - if (key_info & WPA_KEY_INFO_REQUEST) { - if (sm->MICVerified) { - sm->req_replay_counter_used = 1; - 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. */ - sm->key_replay_counter_valid = FALSE; - } - -#ifdef CONFIG_PEERKEY - if (msg == SMK_M3) { - wpa_smk_m3(wpa_auth, sm, key); - return; - } -#endif /* CONFIG_PEERKEY */ - - free(sm->last_rx_eapol_key); - sm->last_rx_eapol_key = malloc(data_len); - if (sm->last_rx_eapol_key == NULL) - return; - 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); - memcpy(sm->SNonce, key->key_nonce, WPA_NONCE_LEN); - wpa_sm_step(sm); -} - - -static void wpa_pmk_to_ptk(const u8 *pmk, const u8 *addr1, const u8 *addr2, - const u8 *nonce1, const u8 *nonce2, - u8 *ptk, size_t ptk_len) -{ - u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN]; - - /* PTK = PRF-X(PMK, "Pairwise key expansion", - * Min(AA, SA) || Max(AA, SA) || - * Min(ANonce, SNonce) || Max(ANonce, SNonce)) */ - - if (memcmp(addr1, addr2, ETH_ALEN) < 0) { - memcpy(data, addr1, ETH_ALEN); - memcpy(data + ETH_ALEN, addr2, ETH_ALEN); - } else { - memcpy(data, addr2, ETH_ALEN); - memcpy(data + ETH_ALEN, addr1, ETH_ALEN); - } - - if (memcmp(nonce1, nonce2, WPA_NONCE_LEN) < 0) { - memcpy(data + 2 * ETH_ALEN, nonce1, WPA_NONCE_LEN); - memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce2, - WPA_NONCE_LEN); - } else { - memcpy(data + 2 * ETH_ALEN, nonce2, WPA_NONCE_LEN); - memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce1, - WPA_NONCE_LEN); - } - - sha1_prf(pmk, WPA_PMK_LEN, "Pairwise key expansion", - data, sizeof(data), ptk, ptk_len); - - wpa_hexdump_key(MSG_DEBUG, "PMK", pmk, WPA_PMK_LEN); - wpa_hexdump_key(MSG_DEBUG, "PTK", ptk, ptk_len); -} - - -static void wpa_gmk_to_gtk(const u8 *gmk, const u8 *addr, const u8 *gnonce, - u8 *gtk, size_t gtk_len) -{ - u8 data[ETH_ALEN + WPA_NONCE_LEN]; - - /* GTK = PRF-X(GMK, "Group key expansion", AA || GNonce) */ - memcpy(data, addr, ETH_ALEN); - memcpy(data + ETH_ALEN, gnonce, WPA_NONCE_LEN); - - sha1_prf(gmk, WPA_GMK_LEN, "Group key expansion", - data, sizeof(data), gtk, gtk_len); - - wpa_hexdump_key(MSG_DEBUG, "GMK", gmk, WPA_GMK_LEN); - wpa_hexdump_key(MSG_DEBUG, "GTK", gtk, gtk_len); -} - - -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; - - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "EAPOL-Key timeout"); - sm->TimeoutEvt = TRUE; - wpa_sm_step(sm); -} - - -static int wpa_calc_eapol_key_mic(int ver, u8 *key, u8 *data, size_t len, - u8 *mic) -{ - u8 hash[SHA1_MAC_LEN]; - - switch (ver) { - case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4: - hmac_md5(key, 16, data, len, mic); - break; - case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES: - hmac_sha1(key, 16, data, len, hash); - memcpy(mic, hash, MD5_MAC_LEN); - break; - default: - return -1; - } - return 0; -} - - -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 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; - - len = sizeof(struct ieee802_1x_hdr) + sizeof(struct wpa_eapol_key); - - if (force_version) - version = force_version; - 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(secure=%d mic=%d ack=%d " - "install=%d pairwise=%d kde_len=%lu keyidx=%d encr=%d)", - (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 && 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 = wpa_zalloc(len); - if (hdr == NULL) - return; - hdr->version = wpa_auth->conf.eapol_version; - hdr->type = IEEE802_1X_TYPE_EAPOL_KEY; - hdr->length = htons(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; - key->key_info = htons(key_info); - - alg = pairwise ? sm->pairwise : wpa_auth->conf.wpa_group; - switch (alg) { - case WPA_CIPHER_CCMP: - key->key_length = htons(16); - break; - case WPA_CIPHER_TKIP: - key->key_length = htons(32); - break; - case WPA_CIPHER_WEP40: - key->key_length = htons(5); - break; - case WPA_CIPHER_WEP104: - key->key_length = htons(13); - break; - } - if (key_info & WPA_KEY_INFO_SMK_MESSAGE) - key->key_length = htons(0); - - /* FIX: STSL: what to use as key_replay_counter? */ - inc_byte_array(sm->key_replay_counter, WPA_REPLAY_COUNTER_LEN); - memcpy(key->replay_counter, sm->key_replay_counter, - WPA_REPLAY_COUNTER_LEN); - sm->key_replay_counter_valid = TRUE; - - if (nonce) - memcpy(key->key_nonce, nonce, WPA_NONCE_LEN); - - if (key_rsc) - memcpy(key->key_rsc, key_rsc, WPA_KEY_RSC_LEN); - - if (kde && !encr) { - memcpy(key + 1, kde, kde_len); - key->key_data_length = htons(kde_len); - } else if (encr && kde) { - buf = wpa_zalloc(key_data_len); - if (buf == NULL) { - free(hdr); - return; - } - pos = buf; - 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) { - aes_wrap(sm->PTK.encr_key, (key_data_len - 8) / 8, buf, - (u8 *) (key + 1)); - key->key_data_length = htons(key_data_len); - } else { - u8 ek[32]; - memcpy(key->key_iv, - sm->group->Counter + WPA_NONCE_LEN - 16, 16); - inc_byte_array(sm->group->Counter, WPA_NONCE_LEN); - memcpy(ek, key->key_iv, 16); - memcpy(ek + 16, sm->PTK.encr_key, 16); - memcpy(key + 1, buf, key_data_len); - rc4_skip(ek, 32, 256, (u8 *) (key + 1), key_data_len); - key->key_data_length = htons(key_data_len); - } - 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"); - free(hdr); - return; - } - wpa_calc_eapol_key_mic(version, - sm->PTK.mic_key, (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); - 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; - - if (sm == NULL) - return; - - __wpa_send_eapol(wpa_auth, sm, key_info, key_rsc, nonce, kde, kde_len, - keyidx, encr, 0); - - timeout_ms = pairwise ? dot11RSNAConfigPairwiseUpdateTimeOut : - dot11RSNAConfigGroupUpdateTimeOut; - 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 = ntohs(key->key_info); - memcpy(mic, key->key_mic, 16); - memset(key->key_mic, 0, 16); - if (wpa_calc_eapol_key_mic(key_info & WPA_KEY_INFO_TYPE_MASK, - PTK->mic_key, data, data_len, key->key_mic) - || memcmp(mic, key->key_mic, 16) != 0) - ret = -1; - memcpy(key->key_mic, mic, 16); - return ret; -} - - -void wpa_remove_ptk(struct wpa_state_machine *sm) -{ - sm->PTK_valid = FALSE; - memset(&sm->PTK, 0, sizeof(sm->PTK)); - wpa_auth_set_key(sm->wpa_auth, 0, "none", sm->addr, 0, (u8 *) "", 0); - sm->pairwise_set = FALSE; -} - - -void wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event) -{ - if (sm == NULL) - return; - - 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: - sm->ReAuthenticationRequest = TRUE; - break; - } - - sm->PTK_valid = FALSE; - memset(&sm->PTK, 0, sizeof(sm->PTK)); - - if (event != WPA_REAUTH_EAPOL) - wpa_remove_ptk(sm); - - wpa_sm_step(sm); -} - - -static const char * wpa_alg_txt(int alg) -{ - switch (alg) { - case WPA_CIPHER_CCMP: - return "CCMP"; - case WPA_CIPHER_TKIP: - return "TKIP"; - case WPA_CIPHER_WEP104: - case WPA_CIPHER_WEP40: - return "WEP"; - default: - return ""; - } -} - - -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 (sm->wpa_key_mgmt == WPA_KEY_MGMT_PSK) { - 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); - 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; -} - - -SM_STATE(WPA_PTK, AUTHENTICATION2) -{ - SM_ENTRY_MA(WPA_PTK, AUTHENTICATION2, wpa_ptk); - memcpy(sm->ANonce, sm->group->Counter, 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) -{ - size_t len = WPA_PMK_LEN; - - SM_ENTRY_MA(WPA_PTK, INITPMK, wpa_ptk); - if (sm->pmksa) { - wpa_printf(MSG_DEBUG, "WPA: PMK from PMKSA cache"); - memcpy(sm->PMK, sm->pmksa->pmk, WPA_PMK_LEN); - } else if (wpa_auth_get_pmk(sm->wpa_auth, sm->addr, sm->PMK, &len) == - 0) { - wpa_printf(MSG_DEBUG, "WPA: PMK from EAPOL state machine " - "(len=%lu)", (unsigned long) len); - } 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) - memcpy(sm->PMK, psk, WPA_PMK_LEN); - 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; - 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 && - sm->wpa_key_mgmt != WPA_KEY_MGMT_PSK) { - pmkid = buf; - pmkid_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN; - pmkid[0] = WLAN_EID_GENERIC; - pmkid[1] = RSN_SELECTOR_LEN + PMKID_LEN; - memcpy(&pmkid[2], RSN_KEY_DATA_PMKID, RSN_SELECTOR_LEN); - if (sm->pmksa) - 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, WPA_PMK_LEN, sm->wpa_auth->addr, - sm->addr, &pmkid[2 + RSN_SELECTOR_LEN]); - } - } - wpa_send_eapol(sm->wpa_auth, sm, - WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE, NULL, - sm->ANonce, pmkid, pmkid_len, 0, 0); - sm->TimeoutCtr++; -} - - -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 (sm->wpa_key_mgmt == WPA_KEY_MGMT_PSK) { - pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, pmk); - if (pmk == NULL) - break; - } else - pmk = sm->PMK; - - wpa_pmk_to_ptk(pmk, sm->wpa_auth->addr, sm->addr, - sm->ANonce, sm->SNonce, - (u8 *) &PTK, sizeof(PTK)); - - if (wpa_verify_key_mic(&PTK, sm->last_rx_eapol_key, - sm->last_rx_eapol_key_len) == 0) { - ok = 1; - break; - } - - if (sm->wpa_key_mgmt != WPA_KEY_MGMT_PSK) - break; - } - - if (!ok) { - wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "invalid MIC in msg 2/4 of 4-Way Handshake"); - return; - } - - eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm); - - if (sm->wpa_key_mgmt == WPA_KEY_MGMT_PSK) { - /* PSK may have changed from the previous choice, so update - * state machine data based on whatever PSK was selected here. - */ - memcpy(sm->PMK, pmk, WPA_PMK_LEN); - } - - sm->MICVerified = TRUE; - - 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_dhv_kde) + - 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_dhv_kde dhv; - struct wpa_igtk_kde igtk; - struct wpa_group *gsm = sm->group; - u8 mac[32]; - const u8 *addr[3]; - size_t len[3]; - - if (!sm->mgmt_frame_prot) - return pos; - - addr[0] = sm->wpa_auth->addr; - len[0] = ETH_ALEN; - addr[1] = sm->addr; - len[1] = ETH_ALEN; - addr[2] = gsm->DGTK; - len[2] = WPA_DGTK_LEN; - sha256_vector(3, addr, len, mac); - memcpy(dhv.dhv, mac, WPA_DHV_LEN); - wpa_hexdump_key(MSG_DEBUG, "WPA: DHV", dhv.dhv, WPA_DHV_LEN); - pos = wpa_add_kde(pos, RSN_KEY_DATA_DHV, - (const u8 *) &dhv, sizeof(dhv), NULL, 0); - - igtk.keyid[0] = gsm->GN; - igtk.keyid[1] = 0; - if (wpa_auth_get_seqnum_igtk(sm->wpa_auth, NULL, gsm->GN, igtk.pn) < 0) - memset(igtk.pn, 0, sizeof(igtk.pn)); - memcpy(igtk.igtk, gsm->IGTK[gsm->GN - 1], 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; - /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, GTK[GN]) - */ - memset(rsc, 0, WPA_KEY_RSC_LEN); - wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc); - 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 & HOSTAPD_WPA_VERSION_WPA2) && - 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; - kde = malloc(kde_len); - if (kde == NULL) - return; - - pos = kde; - memcpy(pos, wpa_ie, wpa_ie_len); - pos += wpa_ie_len; - 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); - - 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); - free(kde); - sm->TimeoutCtr++; -} - - -SM_STATE(WPA_PTK, PTKINITDONE) -{ - SM_ENTRY_MA(WPA_PTK, PTKINITDONE, wpa_ptk); - sm->EAPOLKeyReceived = FALSE; - if (sm->Pair) { - char *alg; - int klen; - if (sm->pairwise == WPA_CIPHER_TKIP) { - alg = "TKIP"; - klen = 32; - } else { - 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_key_mgmt == WPA_KEY_MGMT_PSK) { - 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"); -} - - -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 */) - 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 ((sm->wpa_key_mgmt == WPA_KEY_MGMT_IEEE8021X) && - wpa_auth_get_eapol(sm->wpa_auth, sm->addr, - WPA_EAPOL_keyRun) > 0) - SM_ENTER(WPA_PTK, INITPMK); - else if ((sm->wpa_key_mgmt == WPA_KEY_MGMT_PSK) - /* 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++; - 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++; - 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++; - 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); - 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]) */ - 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 = 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) - free(kde); - sm->GTimeoutCtr++; -} - - -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_ENTER(WPA_PTK_GROUP, IDLE); - 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 void wpa_gtk_update(struct wpa_authenticator *wpa_auth, - struct wpa_group *group) -{ - /* FIX: is this the correct way of getting GNonce? */ - memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN); - inc_byte_array(group->Counter, WPA_NONCE_LEN); - wpa_gmk_to_gtk(group->GMK, wpa_auth->addr, group->GNonce, - group->GTK[group->GN - 1], group->GTK_len); - -#ifdef CONFIG_IEEE80211W - if (wpa_auth->conf.ieee80211w != WPA_NO_IEEE80211W) { - hostapd_get_rand(group->DGTK, WPA_DGTK_LEN); - wpa_hexdump_key(MSG_DEBUG, "DGTK", group->DGTK, WPA_DGTK_LEN); - hostapd_get_rand(group->IGTK[group->GN - 1], WPA_IGTK_LEN); - wpa_hexdump_key(MSG_DEBUG, "IGTK", - group->IGTK[group->GN - 1], WPA_IGTK_LEN); - } -#endif /* CONFIG_IEEE80211W */ -} - - -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 */ - memset(group->GTK, 0, sizeof(group->GTK)); - group->GN = 1; - group->GM = 2; - /* 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"); - return 0; - } - 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; - /* "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); - - wpa_auth_for_each_sta(wpa_auth, wpa_group_update_sta, NULL); - wpa_printf(MSG_DEBUG, "wpa_group_setkeys: GKeyDoneStations=%d", - group->GKeyDoneStations); -} - - -static void 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; - wpa_auth_set_key(wpa_auth, group->vlan_id, - wpa_alg_txt(wpa_auth->conf.wpa_group), - NULL, group->GN, group->GTK[group->GN - 1], - group->GTK_len); - -#ifdef CONFIG_IEEE80211W - if (wpa_auth->conf.ieee80211w != WPA_NO_IEEE80211W) { - wpa_auth_set_key(wpa_auth, group->vlan_id, "IGTK", - NULL, group->GN, group->IGTK[group->GN - 1], - WPA_IGTK_LEN); - wpa_auth_set_key(wpa_auth, group->vlan_id, "DGTK", - NULL, 0, group->DGTK, WPA_DGTK_LEN); - } -#endif /* CONFIG_IEEE80211W */ -} - - -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 void wpa_sm_step(struct wpa_state_machine *sm) -{ - if (sm == NULL) - return; - - 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; - } - - 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); - } -} - - -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; - 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)[0], (s)[1], (s)[2], (s)[3] - -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]; - - if (wpa_auth == NULL) - return len; - - ret = snprintf(buf + len, buflen - len, - "dot11RSNAOptionImplemented=TRUE\n" -#ifdef CONFIG_RSN_PREAUTH - "dot11RSNAPreauthenticationImplemented=TRUE\n" -#else /* CONFIG_RSN_PREAUTH */ - "dot11RSNAPreauthenticationImplemented=FALSE\n" -#endif /* CONFIG_RSN_PREAUTH */ - "dot11RSNAEnabled=%s\n" - "dot11RSNAPreauthenticationEnabled=%s\n", - wpa_bool_txt(wpa_auth->conf.wpa & - HOSTAPD_WPA_VERSION_WPA2), - 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 = 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 = 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; - u8 not_used[4] = { 0, 0, 0, 0 }; - const u8 *pairwise = not_used; - - 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 = snprintf(buf + len, buflen - len, - /* TODO: dot11RSNAStatsIndex */ - "dot11RSNAStatsSTAAddress=" MACSTR "\n" - "dot11RSNAStatsVersion=1\n" - "dot11RSNAStatsSelectedPairwiseCipher=" RSN_SUITE "\n" - /* TODO: dot11RSNAStatsTKIPICVErrors */ - "dot11RSNAStatsTKIPLocalMICFailures=%u\n" - "dot11RSNAStatsTKIPRemoveMICFailures=%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 = 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_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_add(sm->wpa_auth->pmksa, pmk, WPA_PMK_LEN, - sm->wpa_auth->addr, sm->addr, session_timeout, - eapol)) - 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_add(wpa_auth->pmksa, pmk, len, wpa_auth->addr, - sta_addr, session_timeout, eapol)) - 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; -} - -#endif /* CONFIG_NATIVE_WINDOWS */ diff --git a/contrib/hostapd/wpa.h b/contrib/hostapd/wpa.h deleted file mode 100644 index 633b2c56ab17..000000000000 --- a/contrib/hostapd/wpa.h +++ /dev/null @@ -1,186 +0,0 @@ -/* - * hostapd - IEEE 802.11i-2004 / WPA Authenticator - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "wpa_common.h" - -#define WPA_PMK_LEN PMK_LEN -#define WPA_GMK_LEN 32 -#define WPA_GTK_MAX_LEN 32 -#define PMKID_LEN 16 - -#define WPA_CAPABILITY_PREAUTH BIT(0) -#define WPA_CAPABILITY_MGMT_FRAME_PROTECTION BIT(6) -#define WPA_CAPABILITY_PEERKEY_ENABLED BIT(9) - -struct wpa_eapol_key { - u8 type; - u16 key_info; - u16 key_length; - 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 */ - u8 key_mic[16]; - u16 key_data_length; - /* followed by key_data_length bytes of key_data */ -} __attribute__ ((packed)); - -#define WPA_KEY_INFO_TYPE_MASK (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_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) -#define WPA_KEY_INFO_SMK_MESSAGE BIT(13) - - -/* per STA state machine data */ - -struct wpa_ptk { - u8 mic_key[16]; /* EAPOL-Key MIC Key (MK) */ - u8 encr_key[16]; /* EAPOL-Key Encryption Key (EK) */ - 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; -} __attribute__ ((packed)); - -struct wpa_authenticator; -struct wpa_state_machine; -struct rsn_pmksa_cache_entry; - - -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 rsn_preauth; - int eapol_version; - int peerkey; - int wme_enabled; -#ifdef CONFIG_IEEE80211W - enum { - WPA_NO_IEEE80211W = 0, - WPA_IEEE80211W_OPTIONAL = 1, - WPA_IEEE80211W_REQUIRED = 2 - } ieee80211w; -#endif /* CONFIG_IEEE80211W */ -}; - -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_pmk)(void *ctx, const u8 *addr, u8 *pmk, size_t *len); - int (*set_key)(void *ctx, int vlan_id, const char *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 (*get_seqnum_igtk)(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); -}; - -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 -}; - -int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, - const u8 *wpa_ie, size_t wpa_ie_len); -struct wpa_state_machine * -wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr); -void wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth, - 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_event; -void wpa_remove_ptk(struct wpa_state_machine *sm); -void 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_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); - -#endif /* WPA_H */ diff --git a/contrib/hostapd/wpa_common.h b/contrib/hostapd/wpa_common.h deleted file mode 100644 index 6d0316ce4a38..000000000000 --- a/contrib/hostapd/wpa_common.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * WPA definitions shared between hostapd and wpa_supplicant - * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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_REPLAY_COUNTER_LEN 8 -#define WPA_NONCE_LEN 32 -#define WPA_KEY_RSC_LEN 8 - - -/* IEEE Std 802.1X-2004 */ - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -struct ieee802_1x_hdr { - u8 version; - u8 type; - u16 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 }; - -#ifdef CONFIG_IEEE80211W -#define WPA_DGTK_LEN 16 -#define WPA_DHV_LEN 16 -#define WPA_IGTK_LEN 16 -#endif /* CONFIG_IEEE80211W */ - -#endif /* WPA_COMMON_H */ diff --git a/contrib/hostapd/wpa_ctrl.c b/contrib/hostapd/wpa_ctrl.c deleted file mode 100644 index dcec537fc7a2..000000000000 --- a/contrib/hostapd/wpa_ctrl.c +++ /dev/null @@ -1,425 +0,0 @@ -/* - * wpa_supplicant/hostapd control interface library - * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 <sys/un.h> -#endif /* CONFIG_CTRL_IFACE_UNIX */ - -#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 - -struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path) -{ - struct wpa_ctrl *ctrl; - static int counter = 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; - os_snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path), - "/tmp/wpa_ctrl_%d-%d", getpid(), counter++); - if (bind(ctrl->s, (struct sockaddr *) &ctrl->local, - sizeof(ctrl->local)) < 0) { - close(ctrl->s); - os_free(ctrl); - return NULL; - } - - ctrl->dest.sun_family = AF_UNIX; - os_snprintf(ctrl->dest.sun_path, sizeof(ctrl->dest.sun_path), "%s", - ctrl_path); - 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) -{ - unlink(ctrl->local.sun_path); - 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 = 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 = strlen(ctrl->cookie) + 1 + cmd_len; - cmd_buf = os_malloc(_cmd_len ); - if (cmd_buf == NULL) - return -1; - _cmd = cmd_buf; - pos = cmd_buf; - strcpy(pos, ctrl->cookie); - pos += strlen(ctrl->cookie); - *pos++ = ' '; - 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 = 2; - tv.tv_usec = 0; - FD_ZERO(&rfds); - FD_SET(ctrl->s, &rfds); - res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv); - 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; - - ctrl = os_malloc(sizeof(*ctrl)); - if (ctrl == NULL) - return NULL; - os_memset(ctrl, 0, sizeof(*ctrl)); - -#ifdef UNICODE - if (ctrl_path == NULL) - _snwprintf(name, 256, NAMED_PIPE_PREFIX); - else - _snwprintf(name, 256, NAMED_PIPE_PREFIX TEXT("-%S"), - ctrl_path); -#else /* UNICODE */ - if (ctrl_path == NULL) - os_snprintf(name, 256, NAMED_PIPE_PREFIX); - else - os_snprintf(name, 256, NAMED_PIPE_PREFIX "-%s", - ctrl_path); -#endif /* UNICODE */ - - 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/contrib/hostapd/wpa_ctrl.h b/contrib/hostapd/wpa_ctrl.h deleted file mode 100644 index 6166fda26ee9..000000000000 --- a/contrib/hostapd/wpa_ctrl.h +++ /dev/null @@ -1,185 +0,0 @@ -/* - * wpa_supplicant/hostapd control interface library - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 " -/** 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 selected */ -#define WPA_EVENT_EAP_METHOD "CTRL-EVENT-EAP-METHOD " -/** 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 " - - -/* 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/contrib/wpa_supplicant/COPYING b/contrib/wpa_supplicant/COPYING deleted file mode 100644 index 14f5453722a8..000000000000 --- a/contrib/wpa_supplicant/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. - - <one line to give the program's name and a brief idea of what it does.> - Copyright (C) 19yy <name of author> - - 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. - - <signature of Ty Coon>, 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/contrib/wpa_supplicant/ChangeLog b/contrib/wpa_supplicant/ChangeLog deleted file mode 100644 index 10b1aca4a2a6..000000000000 --- a/contrib/wpa_supplicant/ChangeLog +++ /dev/null @@ -1,1049 +0,0 @@ -ChangeLog for wpa_supplicant - -2008-11-28 - v0.5.11 - * fixed race condition between disassociation event and group key - handshake to avoid getting stuck in incorrect state [Bug 261] - * updated D-Bus usage to avoid deprecated functions - * silence SIOCSIWAUTH ioctl failure message (these can be ignored in - most cases and are now only shown in debug output) - * increase timeout for IBSS connection - * driver_wext: do not overwrite BSS frequency if channel was already - received - * driver_wext: set interface down for mode switches, if needed (e.g., - for mac80211) - * driver_wext: fixed re-initialization of a removed and re-inserted - interface (e.g., USB dongle or on resume if driver was unloaded for - suspend) - * improve per-SSID scanning for drivers that report background scan - results frequently - * fixed scanning behavior after a failed initial association - * driver_wext: fixed processing of invalid event messages from kernel - not to crash wpa_supplicant (this could happen when using 64-bit - kernel with 32-bit userspace) - * fixed EAP-AKA to use RES Length field in AT_RES as length in bits, - not bytes - * fixed canceling of PMKSA caching when using drivers that generate - RSN IE and refuse to drop PMKIDs that wpa_supplicant does not know - about - -2008-02-19 - v0.5.10 - * added support for Makefile builds to include debug-log-to-a-file - functionality (CONFIG_DEBUG_FILE=y and -f<path> on command line) - * added network configuration parameter 'frequency' for setting - initial channel for IBSS (adhoc) networks - * fixed EAP-SIM and EAP-AKA message parser to validate attribute - lengths properly to avoid potential crash caused by invalid messages - * added driver_wext workaround for race condition between scanning and - association with drivers that take very long time to scan all - channels (e.g., madwifi with dual-band cards); wpa_supplicant is now - using a longer hardcoded timeout for the scan if the driver supports - notifications for scan completion (SIOCGIWSCAN event); this helps, - e.g., in cases where wpa_supplicant and madwifi driver ended up in - loop where the driver did not even try to associate - * fixed EAP-SIM not to include AT_NONCE_MT and AT_SELECTED_VERSION - attributes in EAP-SIM Start/Response when using fast reauthentication - * fixed problems in getting NDIS events from WMI on Windows 2000 - -2007-12-02 - v0.5.9 - * fixed an integer overflow issue in the ASN.1 parser used by the - (experimental) internal TLS implementation to avoid a potential - buffer read overflow - * fixed a race condition with -W option (wait for a control interface - monitor before starting) that could have caused the first messages to - be lost - * updated EAP Generalized Pre-Shared Key (EAP-GPSK) to use the latest - draft (draft-ietf-emu-eap-gpsk-07.txt) - * added ctrl_iface RECONNECT (wpa_cli reconnect) command - (like reassociate, but only takes effect if already associated) - * fixed a possible race condition between wpa_cli reassociate and - wpa_cli disconnect - * return a non-zero exit code from non-interactive wpa_cli if the - command is not recognized or fails - * fixed 0.5.8 regressions in BSS selection that prevented wildcard SSID - from being used with non-WPA networks and disabled workaround for - ignoring bogus WPA/RSN IE in non-WPA configuration - * fixed OpenSSL TLS wrapper to clear trusted CA list to allow - network blocks to use different trusted CA configurations - * fixed a potential EAP state machine loop when mloving from PSK to EAP - configuration without restarting wpa_supplicant - -2007-05-28 - v0.5.8 - * updated driver_wext.c to build with the current wireless-dev.git tree - and net/d80211 changes - * updated EAP Generalized Pre-Shared Key (EAP-GPSK) to use the latest - draft (draft-ietf-emu-eap-gpsk-03.txt) - * fixed 'make install' - * fixed EAP-TTLS implementation not to crash on use of freed memory - if TLS library initialization fails - * fixed EAP-AKA Notification processing to allow Notification to be - processed after AKA Challenge response has been sent - -2006-12-31 - v0.5.7 - * updated EAP-SAKE to RFC 4763 and the IANA-allocated EAP type 48 - * updated EAP-PSK to use the IANA-allocated EAP type 47 - * fixed EAP-PAX key derivation - * fixed EAP-PSK bit ordering of the Flags field - * fixed EAP-PEAP/TTLS/FAST to use the correct EAP identifier in - tunnelled identity request (previously, the identifier from the outer - method was used, not the tunnelled identifier which could be - different) - * fixed EAP-TTLS AVP parser processing for too short AVP lengths - * added support for EAP-FAST authentication with inner methods that - generate MSK (e.g., EAP-MSCHAPv2 that was previously only supported - for PAC provisioning) - * fixed dbus ctrl_iface to validate message interface before - dispatching to avoid a possible segfault [Bug 190] - * fixed PeerKey key derivation to use the correct PRF label - * updated Windows binary build to link against OpenSSL 0.9.8d and - added support for EAP-FAST - -2006-11-24 - v0.5.6 - * added experimental, integrated TLSv1 client implementation with the - needed X.509/ASN.1/RSA/bignum processing (this can be enabled by - setting CONFIG_TLS=internal and CONFIG_INTERNAL_LIBTOMMATH=y in - .config); this can be useful, e.g., if the target system does not - have a suitable TLS library and a minimal code size is required - (total size of this internal TLS/crypto code is bit under 50 kB on - x86 and the crypto code is shared by rest of the supplicant so some - of it was already required; TLSv1/X.509/ASN.1/RSA added about 25 kB) - * removed STAKey handshake since PeerKey handshake has replaced it in - IEEE 802.11ma and there are no known deployments of STAKey - * updated EAP Generalized Pre-Shared Key (EAP-GPSK) to use the latest - draft (draft-ietf-emu-eap-gpsk-01.txt) - * added preliminary implementation of IEEE 802.11w/D1.0 (management - frame protection) - (Note: this requires driver support to work properly.) - (Note2: IEEE 802.11w is an unapproved draft and subject to change.) - * fixed Windows named pipes ctrl_iface to not stop listening for - commands if client program opens a named pipe and closes it - immediately without sending a command - * fixed USIM PIN status determination for the case that PIN is not - needed (this allows EAP-AKA to be used with USIM cards that do not - use PIN) - * added support for reading 3G USIM AID from EF_DIR to allow EAP-AKA to - be used with cards that do not support file selection based on - partial AID - * added support for matching the subjectAltName of the authentication - server certificate against multiple name components (e.g., - altsubject_match="DNS:server.example.com;DNS:server2.example.com") - * fixed EAP-SIM/AKA key derivation for re-authentication case (only - affects IEEE 802.1X with dynamic WEP keys) - * changed ctrl_iface network configuration 'get' operations to not - return password/key material; if these fields are requested, "*" - will be returned if the password/key is set, but the value of the - parameter is not exposed - -2006-08-27 - v0.5.5 - * added support for building Windows version with UNICODE defined - (wide-char functions) - * driver_ndis: fixed static WEP configuration to avoid race condition - issues with some NDIS drivers between association and setting WEP - keys - * driver_ndis: added validation for IELength value in scan results to - avoid crashes when using buggy NDIS drivers [Bug 165] - * fixed Release|Win32 target in the Visual Studio project files - (previously, only Debug|Win32 target was set properly) - * changed control interface API call wpa_ctrl_pending() to allow it to - return -1 on error (e.g., connection lost); control interface clients - will need to make sure that they verify that the value is indeed >0 - when determining whether there are pending messages - * added an alternative control interface backend for Windows targets: - Named Pipe (CONFIG_CTRL_IFACE=named_pipe); this is now the default - control interface mechanism for Windows builds (previously, UDP to - localhost was used) - * changed ctrl_interface configuration for UNIX domain sockets: - - deprecated ctrl_interface_group variable (it may be removed in - future versions) - - allow both directory and group be configured with ctrl_interface - in following format: DIR=/var/run/wpa_supplicant GROUP=wheel - - ctrl_interface=/var/run/wpa_supplicant is still supported for the - case when group is not changed - * added support for controlling more than one interface per process in - Windows version - * added a workaround for a case where the AP is using unknown address - (e.g., MAC address of the wired interface) as the source address for - EAPOL-Key frames; previously, that source address was used as the - destination for EAPOL-Key frames and in key derivation; now, BSSID is - used even if the source address does not match with it - (this resolves an interoperability issue with Thomson SpeedTouch 580) - * added a workaround for UDP-based control interface (which was used in - Windows builds before this release) to prevent packets with forged - addresses from being accepted as local control requests - * removed ndis_events.cpp and possibility of using external - ndis_events.exe; C version (ndis_events.c) is fully functional and - there is no desire to maintain two separate versions of this - implementation - * ndis_events: Changed NDIS event notification design to use WMI to - learn the adapter description through Win32_PnPEntity class; this - should fix some cases where the adapter name was not recognized - correctly (e.g., with some USB WLAN adapters, e.g., Ralink RT2500 - USB) [Bug 113] - * fixed selection of the first network in ap_scan=2 mode; previously, - wpa_supplicant could get stuck in SCANNING state when only the first - network for enabled (e.g., after 'wpa_cli select_network 0') - * winsvc: added support for configuring ctrl_interface parameters in - registry (ctrl_interface string value in - HKLM\SOFTWARE\wpa_supplicant\interfaces\0000 key); this new value is - required to enable control interface (previously, this was hardcoded - to be enabled) - * allow wpa_gui subdirectory to be built with both Qt3 and Qt4 - * converted wpa_gui-qt4 subdirectory to use Qt4 specific project format - -2006-06-20 - v0.5.4 - * fixed build with CONFIG_STAKEY=y [Bug 143] - * added support for doing MLME (IEEE 802.11 management frame - processing) in wpa_supplicant when using Devicescape IEEE 802.11 - stack (wireless-dev.git tree) - * added a new network block configuration option, fragment_size, to - configure the maximum EAP fragment size - * driver_ndis: Disable WZC automatically for the selected interface to - avoid conflicts with two programs trying to control the radio; WZC - will be re-enabled (if it was enabled originally) when wpa_supplicant - is terminated - * added an experimental TLSv1 client implementation - (CONFIG_TLS=internal) that can be used instead of an external TLS - library, e.g., to reduce total size requirement on systems that do - not include any TLS library by default (this is not yet complete; - basic functionality is there, but certificate validation is not yet - included) - * added PeerKey handshake implementation for IEEE 802.11e - direct link setup (DLS) to replace STAKey handshake - * fixed WPA PSK update through ctrl_iface for the case where the old - PSK was derived from an ASCII passphrase and the new PSK is set as - a raw PSK (hex string) - * added new configuration option for identifying which network block - was used (id_str in wpa_supplicant.conf; included on - WPA_EVENT_CONNECT monitor event and as WPA_ID_STR environmental - variable in wpa_cli action scripts; in addition WPA_ID variable is - set to the current unique identifier that wpa_supplicant assigned - automatically for the network and that can be used with - GET_NETWORK/SET_NETWORK ctrl_iface commands) - * wpa_cli action script is now called only when the connect/disconnect - status changes or when associating with a different network - * fixed configuration parser not to remove CCMP from group cipher list - if WPA-None (adhoc) is used (pairwise=NONE in that case) - * fixed integrated NDIS events processing not to hang the process due - to a missed change in eloop_win.c API in v0.5.3 [Bug 155] - * added support for EAP Generalized Pre-Shared Key (EAP-GPSK, - draft-clancy-emu-eap-shared-secret-00.txt) - * added Microsoft Visual Studio 2005 solution and project files for - build wpa_supplicant for Windows (see vs2005 subdirectory) - * eloop_win: fixed unregistration of Windows events - * l2_packet_winpcap: fixed a deadlock in deinitializing l2_packet - at the end of RSN pre-authentication and added unregistration of - a Windows event to avoid getting eloop_win stuck with an invalid - handle - * driver_ndis: added support for selecting AP based on BSSID - * added new environmental variable for wpa_cli action scripts: - WPA_CTRL_DIR is the current control interface directory - * driver_ndis: added support for using NDISUIO instead of WinPcap for - OID set/query operations (CONFIG_USE_NDISUIO=y in .config); with new - l2_packet_ndis (CONFIG_L2_PACKET=ndis), this can be used to build - wpa_supplicant without requiring WinPcap; note that using NDISUIO - requires that WZC is disabled (net stop wzcsvc) since NDISUIO allows - only one application to open the device - * changed NDIS driver naming to only include device GUID, e.g., - {7EE3EFE5-C165-472F-986D-F6FBEDFE8C8D}, instead of including WinPcap - specific \Device\NPF_ prefix before the GUID; the prefix is still - allowed for backwards compatibility, but it is not required anymore - when specifying the interface - * driver_ndis: re-initialize driver interface is the adapter is removed - and re-inserted [Bug 159] - * driver_madwifi: fixed TKIP and CCMP sequence number configuration on - big endian hosts [Bug 146] - -2006-04-27 - v0.5.3 - * fixed EAP-GTC response to include correct user identity when run as - phase 2 method of EAP-FAST (i.e., EAP-FAST did not work in v0.5.2) - * driver_ndis: Fixed encryption mode configuration for unencrypted - networks (some NDIS drivers ignored this, but others, e.g., Broadcom, - refused to associate with open networks) [Bug 106] - * driver_ndis: use BSSID OID polling to detect when IBSS network is - formed even when ndis_events code is included since some NDIS drivers - do not generate media connect events in IBSS mode - * config_winreg: allow global ctrl_interface parameter to be configured - in Windows registry - * config_winreg: added support for saving configuration data into - Windows registry - * added support for controlling network device operational state - (dormant/up) for Linux 2.6.17 to improve DHCP processing (see - http://www.flamewarmaster.de/software/dhcpclient/ for a DHCP client - that can use this information) - * driver_wext: added support for WE-21 change to SSID configuration - * driver_wext: fixed privacy configuration for static WEP keys mode - [Bug 140] - * added an optional driver_ops callback for MLME-SETPROTECTION.request - primitive - * added support for EAP-SAKE (no EAP method number allocated yet, so - this is using the same experimental type 255 as EAP-PSK) - * added support for dynamically loading EAP methods (.so files) instead - of requiring them to be statically linked in; this is disabled by - default (see CONFIG_DYNAMIC_EAP_METHODS in defconfig for information - on how to use this) - -2006-03-19 - v0.5.2 - * do not try to use USIM APDUs when initializing PC/SC for SIM card - access for a network that has not enabled EAP-AKA - * fixed EAP phase 2 Nak for EAP-{PEAP,TTLS,FAST} (this was broken in - v0.5.1 due to the new support for expanded EAP types) - * added support for generating EAP Expanded Nak - * try to fetch scan results once before requesting new scan when - starting up in ap_scan=1 mode (this can speed up initial association - a lot with, e.g., madwifi-ng driver) - * added support for receiving EAPOL frames from a Linux bridge - interface (-bbr0 on command line) - * fixed EAPOL re-authentication for sessions that used PMKSA caching - * changed EAP method registration to use a dynamic list of methods - instead of a static list generated at build time - * fixed PMKSA cache deinitialization not to use freed memory when - removing PMKSA entries - * fixed a memory leak in EAP-TTLS re-authentication - * reject WPA/WPA2 message 3/4 if it does not include any valid - WPA/RSN IE - * driver_wext: added fallback to use SIOCSIWENCODE for setting auth_alg - if the driver does not support SIOCSIWAUTH - -2006-01-29 - v0.5.1 - * driver_test: added better support for multiple APs and STAs by using - a directory with sockets that include MAC address for each device in - the name (driver_param=test_dir=/tmp/test) - * added support for EAP expanded type (vendor specific EAP methods) - * added AP_SCAN command into ctrl_iface so that ap_scan configuration - option can be changed if needed - * wpa_cli/wpa_gui: skip non-socket files in control directory when - using UNIX domain sockets; this avoids selecting an incorrect - interface (e.g., a PID file could be in this directory, even though - use of this directory for something else than socket files is not - recommended) - * fixed TLS library deinitialization after RSN pre-authentication not - to disable TLS library for normal authentication - * driver_wext: Remove null-termination from SSID length if the driver - used it; some Linux drivers do this and they were causing problems in - wpa_supplicant not finding matching configuration block. This change - would break a case where the SSID actually ends in '\0', but that is - not likely to happen in real use. - * fixed PMKSA cache processing not to trigger deauthentication if the - current PMKSA cache entry is replaced with a valid new entry - * fixed PC/SC initialization for ap_scan != 1 modes (this fixes - EAP-SIM and EAP-AKA with real SIM/USIM card when using ap_scan=0 or - ap_scan=2) - -2005-12-18 - v0.5.0 (beginning of 0.5.x development releases) - * added experimental STAKey handshake implementation for IEEE 802.11e - direct link setup (DLS); note: this is disabled by default in both - build and runtime configuration (can be enabled with CONFIG_STAKEY=y - and stakey=1) - * fixed EAP-SIM and EAP-AKA pseudonym and fast re-authentication to - decrypt AT_ENCR_DATA attributes correctly - * fixed EAP-AKA to allow resynchronization within the same session - * made code closer to ANSI C89 standard to make it easier to port to - other C libraries and compilers - * started moving operating system or C library specific functions into - wrapper functions defined in os.h and implemented in os_*.c to make - code more portable - * wpa_supplicant can now be built with Microsoft Visual C++ - (e.g., with the freely available Toolkit 2003 version or Visual - C++ 2005 Express Edition and Platform SDK); see nmake.mak for an - example makefile for nmake - * added support for using Windows registry for command line parameters - (CONFIG_MAIN=main_winsvc) and configuration data - (CONFIG_BACKEND=winreg); see win_example.reg for an example registry - contents; this version can be run both as a Windows service and as a - normal application; 'wpasvc.exe app' to start as applicant, - 'wpasvc.exe reg <full path to wpasvc.exe>' to register a service, - 'net start wpasvc' to start the service, 'wpasvc.exe unreg' to - unregister a service - * made it possible to link ndis_events.exe functionality into - wpa_supplicant.exe by defining CONFIG_NDIS_EVENTS_INTEGRATED - * added better support for multiple control interface backends - (CONFIG_CTRL_IFACE option); currently, 'unix' and 'udp' are supported - * fixed PC/SC code to use correct length for GSM AUTH command buffer - and to not use pioRecvPci with SCardTransmit() calls; these were not - causing visible problems with pcsc-lite, but Windows Winscard.dll - refused the previously used parameters; this fixes EAP-SIM and - EAP-AKA authentication using SIM/USIM card under Windows - * added new event loop implementation for Windows using - WaitForMultipleObject() instead of select() in order to allow waiting - for non-socket objects; this can be selected with - CONFIG_ELOOP=eloop_win in .config - * added support for selecting l2_packet implementation in .config - (CONFIG_L2_PACKET; following options are available now: linux, pcap, - winpcap, freebsd, none) - * added new l2_packet implementation for WinPcap - (CONFIG_L2_PACKET=winpcap) that uses a separate receive thread to - reduce latency in EAPOL receive processing from about 100 ms to about - 3 ms - * added support for EAP-FAST key derivation using other ciphers than - RC4-128-SHA for authentication and AES128-SHA for provisioning - * added support for configuring CA certificate as DER file and as a - configuration blob - * fixed private key configuration as configuration blob and added - support for using PKCS#12 as a blob - * tls_gnutls: added support for using PKCS#12 files; added support for - session resumption - * added support for loading trusted CA certificates from Windows - certificate store: ca_cert="cert_store://<name>", where <name> is - likely CA (Intermediate CA certificates) or ROOT (root certificates) - * added C version of ndis_events.cpp and made it possible to build this - with MinGW so that CONFIG_NDIS_EVENTS_INTEGRATED can be used more - easily on cross-compilation builds - * added wpasvc.exe into Windows binary release; this is an alternative - version of wpa_supplicant.exe with configuration backend using - Windows registry and with the entry point designed to run as a - Windows service - * integrated ndis_events.exe functionality into wpa_supplicant.exe and - wpasvc.exe and removed this additional tool from the Windows binary - release since it is not needed anymore - * load winscard.dll functions dynamically when building with MinGW - since MinGW does not yet include winscard library - -2005-11-20 - v0.4.7 (beginning of 0.4.x stable releases) - * l2_packet_pcap: fixed wired IEEE 802.1X authentication with libpcap - and WinPcap to receive frames sent to PAE group address - * disable EAP state machine when IEEE 802.1X authentication is not used - in order to get rid of bogus "EAP failed" messages - * fixed OpenSSL error reporting to go through all pending errors to - avoid confusing reports of old errors being reported at later point - during handshake - * fixed configuration file updating to not write empty variables - (e.g., proto or key_mgmt) that the file parser would not accept - * fixed ADD_NETWORK ctrl_iface command to use the same default values - for variables as empty network definitions read from config file - would get - * fixed EAP state machine to not discard EAP-Failure messages in many - cases (e.g., during TLS handshake) - * fixed a infinite loop in private key reading if the configured file - cannot be parsed successfully - * driver_madwifi: added support for madwifi-ng - * wpa_gui: do not display password/PSK field contents - * wpa_gui: added CA certificate configuration - * driver_ndis: fixed scan request in ap_scan=2 mode not to change SSID - * driver_ndis: include Beacon IEs in AssocInfo in order to notice if - the new AP is using different WPA/RSN IE - * use longer timeout for IEEE 802.11 association to avoid problems with - drivers that may take more than five second to associate - -2005-10-27 - v0.4.6 - * allow fallback to WPA, if mixed WPA+WPA2 networks have mismatch in - RSN IE, but WPA IE would match with wpa_supplicant configuration - * added support for named configuration blobs in order to avoid having - to use file system for external files (e.g., certificates); - variables can be set to "blob://<blob name>" instead of file path to - use a named blob; supported fields: pac_file, client_cert, - private_key - * fixed RSN pre-authentication (it was broken in the clean up of WPA - state machine interface in v0.4.5) - * driver_madwifi: set IEEE80211_KEY_GROUP flag for group keys to make - sure the driver configures broadcast decryption correctly - * added ca_path (and ca_path2) configuration variables that can be used - to configure OpenSSL CA path, e.g., /etc/ssl/certs, for using the - system-wide trusted CA list - * added support for starting wpa_supplicant without a configuration - file (-C argument must be used to set ctrl_interface parameter for - this case; in addition, -p argument can be used to provide - driver_param; these new arguments can also be used with a - configuration to override the values from the configuration) - * added global control interface that can be optionally used for adding - and removing network interfaces dynamically (-g command line argument - for both wpa_supplicant and wpa_cli) without having to restart - wpa_supplicant process - * wpa_gui: - - try to save configuration whenever something is modified - - added WEP key configuration - - added possibility to edit the current network configuration - * driver_ndis: fixed driver polling not to increase frequency on each - received EAPOL frame due to incorrectly cancelled timeout - * added simple configuration file examples (in examples subdirectory) - * fixed driver_wext.c to filter wireless events based on ifindex to - avoid interfaces receiving events from other interfaces - * delay sending initial EAPOL-Start couple of seconds to speed up - authentication for the most common case of Authenticator starting - EAP authentication immediately after association - -2005-09-25 - v0.4.5 - * added a workaround for clearing keys with ndiswrapper to allow - roaming from WPA enabled AP to plaintext one - * added docbook documentation (doc/docbook) that can be used to - generate, e.g., man pages - * l2_packet_linux: use socket type SOCK_DGRAM instead of SOCK_RAW for - PF_PACKET in order to prepare for network devices that do not use - Ethernet headers (e.g., network stack with native IEEE 802.11 frames) - * use receipt of EAPOL-Key frame as a lower layer success indication - for EAP state machine to allow recovery from dropped EAP-Success - frame - * cleaned up internal EAPOL frame processing by not including link - layer (Ethernet) header during WPA and EAPOL/EAP processing; this - header is added only when transmitted the frame; this makes it easier - to use wpa_supplicant on link layers that use different header than - Ethernet - * updated EAP-PSK to use draft 9 by default since this can now be - tested with hostapd; removed support for draft 3, including - server_nai configuration option from network blocks - * driver_wired: add PAE address to the multicast address list in order - to be able to receive EAPOL frames with drivers that do not include - these multicast addresses by default - * driver_wext: add support for WE-19 - * added support for multiple configuration backends (CONFIG_BACKEND - option); currently, only 'file' is supported (i.e., the format used - in wpa_supplicant.conf) - * added support for updating configuration ('wpa_cli save_config'); - this is disabled by default and can be enabled with global - update_config=1 variable in wpa_supplicant.conf; this allows wpa_cli - and wpa_gui to store the configuration changes in a permanent store - * added GET_NETWORK ctrl_iface command - (e.g., 'wpa_cli get_network 0 ssid') - -2005-08-21 - v0.4.4 - * replaced OpenSSL patch for EAP-FAST support - (openssl-tls-extensions.patch) with a more generic and correct - patch (the new patch is not compatible with the previous one, so the - OpenSSL library will need to be patched with the new patch in order - to be able to build wpa_supplicant with EAP-FAST support) - * added support for using Windows certificate store (through CryptoAPI) - for client certificate and private key operations (EAP-TLS) - (see wpa_supplicant.conf for more information on how to configure - this with private_key) - * ported wpa_gui to Windows - * added Qt4 version of wpa_gui (wpa_gui-qt4 directory); this can be - built with the open source version of the Qt4 for Windows - * allow non-WPA modes (e.g., IEEE 802.1X with dynamic WEP) to be used - with drivers that do not support WPA - * ndis_events: fixed Windows 2000 support - * added support for enabling/disabling networks from the list of all - configured networks ('wpa_cli enable_network <network id>' and - 'wpa_cli disable_network <network id>') - * added support for adding and removing network from the current - configuration ('wpa_cli add_network' and 'wpa_cli remove_network - <network id>'); added networks are disabled by default and they can - be enabled with enable_network command once the configuration is done - for the new network; note: configuration file is not yet updated, so - these new networks are lost when wpa_supplicant is restarted - * added support for setting network configuration parameters through - the control interface, for example: - wpa_cli set_network 0 ssid "\"my network\"" - * fixed parsing of strings that include both " and # within double - quoted area (e.g., "start"#end") - * added EAP workaround for PEAP session resumption: allow outer, - i.e., not tunneled, EAP-Success to terminate session since; this can - be disabled with eap_workaround=0 - (this was allowed for PEAPv1 before, but now it is also allowed for - PEAPv0 since at least one RADIUS authentication server seems to be - doing this for PEAPv0, too) - * wpa_gui: added preliminary support for adding new networks to the - wpa_supplicant configuration (double click on the scan results to - open network configuration) - -2005-06-26 - v0.4.3 - * removed interface for external EAPOL/EAP supplicant (e.g., - Xsupplicant), (CONFIG_XSUPPLICANT_IFACE) since it is not required - anymore and is unlikely to be used by anyone - * driver_ndis: fixed WinPcap 3.0 support - * fixed build with CONFIG_DNET_PCAP=y on Linux - * l2_packet: moved different implementations into separate files - (l2_packet_*.c) - -2005-06-12 - v0.4.2 - * driver_ipw: updated driver structures to match with ipw2200-1.0.4 - (note: ipw2100-1.1.0 is likely to require an update to work with - this) - * added support for using ap_scan=2 mode with multiple network blocks; - wpa_supplicant will go through the networks one by one until the - driver reports a successful association; this uses the same order for - networks as scan_ssid=1 scans, i.e., the priority field is ignored - and the network block order in the file is used instead - * fixed a potential issue in RSN pre-authentication ending up using - freed memory if pre-authentication times out - * added support for matching alternative subject name extensions of the - authentication server certificate; new configuration variables - altsubject_match and altsubject_match2 - * driver_ndis: added support for IEEE 802.1X authentication with wired - NDIS drivers - * added support for querying private key password (EAP-TLS) through the - control interface (wpa_cli/wpa_gui) if one is not included in the - configuration file - * driver_broadcom: fixed couple of memory leaks in scan result - processing - * EAP-PAX is now registered as EAP type 46 - * fixed EAP-PAX MAC calculation - * fixed EAP-PAX CK and ICK key derivation - * added support for using password with EAP-PAX (as an alternative to - entering key with eappsk); SHA-1 hash of the password will be used as - the key in this case - * added support for arbitrary driver interface parameters through the - configuration file with a new driver_param field; this adds a new - driver_ops function set_param() - * added possibility to override l2_packet module with driver interface - API (new send_eapol handler); this can be used to implement driver - specific TX/RX functions for EAPOL frames - * fixed ctrl_interface_group processing for the case where gid is - entered as a number, not group name - * driver_test: added support for testing hostapd with wpa_supplicant - by using test driver interface without any kernel drivers or network - cards - -2005-05-22 - v0.4.1 - * driver_madwifi: fixed WPA/WPA2 mode configuration to allow EAPOL - packets to be encrypted; this was apparently broken by the changed - ioctl order in v0.4.0 - * driver_madwifi: added preliminary support for compiling against 'BSD' - branch of madwifi CVS tree - * added support for EAP-MSCHAPv2 password retries within the same EAP - authentication session - * added support for password changes with EAP-MSCHAPv2 (used when the - password has expired) - * added support for reading additional certificates from PKCS#12 files - and adding them to the certificate chain - * fixed association with IEEE 802.1X (no WPA) when dynamic WEP keys - were used - * fixed a possible double free in EAP-TTLS fast-reauthentication when - identity or password is entered through control interface - * display EAP Notification messages to user through control interface - with "CTRL-EVENT-EAP-NOTIFICATION" prefix - * added GUI version of wpa_cli, wpa_gui; this is not build - automatically with 'make'; use 'make wpa_gui' to build (this requires - Qt development tools) - * added 'disconnect' command to control interface for setting - wpa_supplicant in state where it will not associate before - 'reassociate' command has been used - * added support for selecting a network from the list of all configured - networks ('wpa_cli select_network <network id>'; this disabled all - other networks; to re-enable, 'wpa_cli select_network any') - * added support for getting scan results through control interface - * added EAP workaround for PEAPv1 session resumption: allow outer, - i.e., not tunneled, EAP-Success to terminate session since; this can - be disabled with eap_workaround=0 - -2005-04-25 - v0.4.0 (beginning of 0.4.x development releases) - * added a new build time option, CONFIG_NO_STDOUT_DEBUG, that can be - used to reduce the size of the wpa_supplicant considerably if - debugging code is not needed - * fixed EAPOL-Key validation to drop packets with invalid Key Data - Length; such frames could have crashed wpa_supplicant due to buffer - overflow - * added support for wired authentication (IEEE 802.1X on wired - Ethernet); driver interface 'wired' - * obsoleted set_wpa() handler in the driver interface API (it can be - replaced by moving enable/disable functionality into init()/deinit()) - (calls to set_wpa() are still present for backwards compatibility, - but they may be removed in the future) - * driver_madwifi: fixed association in plaintext mode - * modified the EAP workaround that accepts EAP-Success with incorrect - Identifier to be even less strict about verification in order to - interoperate with some authentication servers - * added support for sending TLS alerts - * added support for 'any' SSID wildcard; if ssid is not configured or - is set to an empty string, any SSID will be accepted for non-WPA AP - * added support for asking PIN (for SIM) from frontends (e.g., - wpa_cli); if a PIN is needed, but not included in the configuration - file, a control interface request is sent and EAP processing is - delayed until the PIN is available - * added support for using external devices (e.g., a smartcard) for - private key operations in EAP-TLS (CONFIG_SMARTCARD=y in .config); - new wpa_supplicant.conf variables: - - global: opensc_engine_path, pkcs11_engine_path, pkcs11_module_path - - network: engine, engine_id, key_id - * added experimental support for EAP-PAX - * added monitor mode for wpa_cli (-a<path to a program to run>) that - allows external commands (e.g., shell scripts) to be run based on - wpa_supplicant events, e.g., when authentication has been completed - and data connection is ready; other related wpa_cli arguments: - -B (run in background), -P (write PID file); wpa_supplicant has a new - command line argument (-W) that can be used to make it wait until a - control interface command is received in order to avoid missing - events - * added support for opportunistic WPA2 PMKSA key caching (disabled by - default, can be enabled with proactive_key_caching=1) - * fixed RSN IE in 4-Way Handshake message 2/4 for the case where - Authenticator rejects PMKSA caching attempt and the driver is not - using assoc_info events - * added -P<pid file> argument for wpa_supplicant to write the current - process id into a file - -2005-02-12 - v0.3.7 (beginning of 0.3.x stable releases) - * added new phase1 option parameter, include_tls_length=1, to force - wpa_supplicant to add TLS Message Length field to all TLS messages - even if the packet is not fragmented; this may be needed with some - authentication servers - * fixed WPA/RSN IE verification in message 3 of 4-Way Handshake when - using drivers that take care of AP selection (e.g., when using - ap_scan=2) - * fixed reprocessing of pending request after ctrl_iface requests for - identity/password/otp - * fixed ctrl_iface requests for identity/password/otp in Phase 2 of - EAP-PEAP and EAP-TTLS - * all drivers using driver_wext: set interface up and select Managed - mode when starting wpa_supplicant; set interface down when exiting - * renamed driver_ipw2100.c to driver_ipw.c since it now supports both - ipw2100 and ipw2200; please note that this also changed the - configuration variable in .config to CONFIG_DRIVER_IPW - -2005-01-24 - v0.3.6 - * fixed a busy loop introduced in v0.3.5 for scan result processing - when no matching AP is found - -2005-01-23 - v0.3.5 - * added a workaround for an interoperability issue with a Cisco AP - when using WPA2-PSK - * fixed non-WPA IEEE 802.1X to use the same authentication timeout as - WPA with IEEE 802.1X (i.e., timeout 10 -> 70 sec to allow - retransmission of dropped frames) - * fixed issues with 64-bit CPUs and SHA1 cleanup in previous version - (e.g., segfault when processing EAPOL-Key frames) - * fixed EAP workaround and fast reauthentication configuration for - RSN pre-authentication; previously these were disabled and - pre-authentication would fail if the used authentication server - requires EAP workarounds - * added support for blacklisting APs that fail or timeout - authentication in ap_scan=1 mode so that all APs are tried in cases - where the ones with strongest signal level are failing authentication - * fixed CA certificate loading after a failed EAP-TLS/PEAP/TTLS - authentication attempt - * allow EAP-PEAP/TTLS fast reauthentication only if Phase 2 succeeded - in the previous authentication (previously, only Phase 1 success was - verified) - -2005-01-09 - v0.3.4 - * added preliminary support for IBSS (ad-hoc) mode configuration - (mode=1 in network block); this included a new key_mgmt mode - WPA-NONE, i.e., TKIP or CCMP with a fixed key (based on psk) and no - key management; see wpa_supplicant.conf for more details and an - example on how to configure this (note: this is currently implemented - only for driver_hostapd.c, but the changes should be trivial to add - in associate() handler for other drivers, too (assuming the driver - supports WPA-None) - * added preliminary port for native Windows (i.e., no cygwin) using - mingw - -2005-01-02 - v0.3.3 - * added optional support for GNU Readline and History Libraries for - wpa_cli (CONFIG_READLINE) - * cleaned up EAP state machine <-> method interface and number of - small problems with error case processing not terminating on - EAP-Failure but waiting for timeout - * added couple of workarounds for interoperability issues with a - Cisco AP when using WPA2 - * added support for EAP-FAST (draft-cam-winget-eap-fast-00.txt); - Note: This requires a patch for openssl to add support for TLS - extensions and number of workarounds for operations without - certificates. Proof of concept type of experimental patch is - included in openssl-tls-extensions.patch. - -2004-12-19 - v0.3.2 - * fixed private key loading for cases where passphrase is not set - * fixed Windows/cygwin L2 packet handler freeing; previous version - could cause a segfault when RSN pre-authentication was completed - * added support for PMKSA caching with drivers that generate RSN IEs - (e.g., NDIS); currently, this is only implemented in driver_ndis.c, - but similar code can be easily added to driver_ndiswrapper.c once - ndiswrapper gets full support for RSN PMKSA caching - * improved recovery from PMKID mismatches by requesting full EAP - authentication in case of failed PMKSA caching attempt - * driver_ndis: added support for NDIS NdisMIncidateStatus() events - (this requires that ndis_events is ran while wpa_supplicant is - running) - * driver_ndis: use ADD_WEP/REMOVE_WEP when configuring WEP keys - * added support for driver interfaces to replace the interface name - based on driver/OS specific mapping, e.g., in case of driver_ndis, - this allows the beginning of the adapter description to be used as - the interface name - * added support for CR+LF (Windows-style) line ends in configuration - file - * driver_ndis: enable radio before starting scanning, disable radio - when exiting - * modified association event handler to set portEnabled = FALSE before - clearing port Valid in order to reset EAP state machine and avoid - problems with new authentication getting ignored because of state - machines ending up in AUTHENTICATED/SUCCESS state based on old - information - * added support for driver events to add PMKID candidates in order to - allow drivers to give priority to most likely roaming candidates - * driver_hostap: moved PrivacyInvoked configuration to associate() - function so that this will not be set for plaintext connections - * added KEY_MGMT_802_1X_NO_WPA as a new key_mgmt type so that driver - interface can distinguish plaintext and IEEE 802.1X (no WPA) - authentication - * fixed static WEP key configuration to use broadcast/default type for - all keys (previously, the default TX key was configured as pairwise/ - unicast key) - * driver_ndis: added legacy WPA capability detection for non-WPA2 - drivers - * added support for setting static WEP keys for IEEE 802.1X without - dynamic WEP keying (eapol_flags=0) - -2004-12-12 - v0.3.1 - * added support for reading PKCS#12 (PFX) files (as a replacement for - PEM/DER) to get certificate and private key (CONFIG_PKCS12) - * fixed compilation with CONFIG_PCSC=y - * added new ap_scan mode, ap_scan=2, for drivers that take care of - association, but need to be configured with security policy and SSID, - e.g., ndiswrapper and NDIS driver; this mode should allow such - drivers to work with hidden SSIDs and optimized roaming; when - ap_scan=2 is used, only the first network block in the configuration - file is used and this configuration should have explicit security - policy (i.e., only one option in the lists) for key_mgmt, pairwise, - group, proto variables - * added experimental port of wpa_supplicant for Windows - - driver_ndis.c driver interface (NDIS OIDs) - - currently, this requires cygwin and WinPcap - - small utility, win_if_list, can be used to get interface name - * control interface can now be removed at build time; add - CONFIG_CTRL_IFACE=y to .config to maintain old functionality - * optional Xsupplicant interface can now be removed at build time; - (CONFIG_XSUPPLICANT_IFACE=y in .config to bring it back) - * added auth_alg to driver interface associate() parameters to make it - easier for drivers to configure authentication algorithm as part of - the association - -2004-12-05 - v0.3.0 (beginning of 0.3.x development releases) - * driver_broadcom: added new driver interface for Broadcom wl.o driver - (a generic driver for Broadcom IEEE 802.11a/g cards) - * wpa_cli: fixed parsing of -p <path> command line argument - * PEAPv1: fixed tunneled EAP-Success reply handling to reply with TLS - ACK, not tunneled EAP-Success (of which only the first byte was - actually send due to a bug in previous code); this seems to - interoperate with most RADIUS servers that implements PEAPv1 - * PEAPv1: added support for terminating PEAP authentication on tunneled - EAP-Success message; this can be configured by adding - peap_outer_success=0 on phase1 parameters in wpa_supplicant.conf - (some RADIUS servers require this whereas others require a tunneled - reply - * PEAPv1: changed phase1 option peaplabel to use default to 0, i.e., to - the old label for key derivation; previously, the default was 1, - but it looks like most existing PEAPv1 implementations use the old - label which is thus more suitable default option - * added support for EAP-PSK (draft-bersani-eap-psk-03.txt) - * fixed parsing of wep_tx_keyidx - * added support for configuring list of allowed Phase 2 EAP types - (for both EAP-PEAP and EAP-TTLS) instead of only one type - * added support for configuring IEEE 802.11 authentication algorithm - (auth_alg; mainly for using Shared Key authentication with static - WEP keys) - * added support for EAP-AKA (with UMTS SIM) - * fixed couple of errors in PCSC handling that could have caused - random-looking errors for EAP-SIM - * added support for EAP-SIM pseudonyms and fast re-authentication - * added support for EAP-TLS/PEAP/TTLS fast re-authentication (TLS - session resumption) - * added support for EAP-SIM with two challanges - (phase1="sim_min_num_chal=3" can be used to require three challenges) - * added support for configuring DH/DSA parameters for an ephemeral DH - key exchange (EAP-TLS/PEAP/TTLS) using new configuration parameters - dh_file and dh_file2 (phase 2); this adds support for using DSA keys - and optional DH key exchange to achieve forward secracy with RSA keys - * added support for matching subject of the authentication server - certificate with a substring when using EAP-TLS/PEAP/TTLS; new - configuration variables subject_match and subject_match2 - * changed SSID configuration in driver_wext.c (used by many driver - interfaces) to use ssid_len+1 as the length for SSID since some Linux - drivers expect this - * fixed couple of unaligned reads in scan result parsing to fix WPA - connection on some platforms (e.g., ARM) - * added driver interface for Intel ipw2100 driver - * added support for LEAP with WPA - * added support for larger scan results report (old limit was 4 kB of - data, i.e., about 35 or so APs) when using Linux wireless extensions - v17 or newer - * fixed a bug in PMKSA cache processing: skip sending of EAPOL-Start - only if there is a PMKSA cache entry for the current AP - * fixed error handling for case where reading of scan results fails: - must schedule a new scan or wpa_supplicant will remain waiting - forever - * changed debug output to remove shared password/key material by - default; all key information can be included with -K command line - argument to match the previous behavior - * added support for timestamping debug log messages (disabled by - default, can be enabled with -t command line argument) - * set pairwise/group cipher suite for non-WPA IEEE 802.1X to WEP-104 - if keys are not configured to be used; this fixes IEEE 802.1X mode - with drivers that use this information to configure whether Privacy - bit can be in Beacon frames (e.g., ndiswrapper) - * avoid clearing driver keys if no keys have been configured since last - key clear request; this seems to improve reliability of group key - handshake for ndiswrapper & NDIS driver which seems to be suffering - of some kind of timing issue when the keys are cleared again after - association - * changed driver interface API: - - WPA_SUPPLICANT_DRIVER_VERSION define can be used to determine which - version is being used (now, this is set to 2; previously, it was - not defined) - - pass pointer to private data structure to all calls - - the new API is not backwards compatible; all in-tree driver - interfaces has been converted to the new API - * added support for controlling multiple interfaces (radios) per - wpa_supplicant process; each interface needs to be listed on the - command line (-c, -i, -D arguments) with -N as a separator - (-cwpa1.conf -iwlan0 -Dhostap -N -cwpa2.conf -iath0 -Dmadwifi) - * added a workaround for EAP servers that incorrectly use same Id for - sequential EAP packets - * changed libpcap/libdnet configuration to use .config variable, - CONFIG_DNET_PCAP, instead of requiring Makefile modification - * improved downgrade attack detection in IE verification of msg 3/4: - verify both WPA and RSN IEs, if present, not only the selected one; - reject the AP if an RSN IE is found in msg 3/4, but not in Beacon or - Probe Response frame, and RSN is enabled in wpa_supplicant - configuration - * fixed WPA msg 3/4 processing to allow Key Data field contain other - IEs than just one WPA IE - * added support for FreeBSD and driver interface for the BSD net80211 - layer (CONFIG_DRIVER_BSD=y in .config); please note that some of the - required kernel mods have not yet been committed - * made EAP workarounds configurable; enabled by default, can be - disabled with network block option eap_workaround=0 - -2004-07-17 - v0.2.4 (beginning of 0.2.x stable releases) - * resolved couple of interoperability issues with EAP-PEAPv1 and - Phase 2 (inner EAP) fragment reassembly - * driver_madwifi: fixed WEP key configuration for IEEE 802.1X when the - AP is using non-zero key index for the unicast key and key index zero - for the broadcast key - * driver_hostap: fixed IEEE 802.1X WEP key updates and - re-authentication by allowing unencrypted EAPOL frames when not using - WPA - * added a new driver interface, 'wext', which uses only standard, - driver independent functionality in Linux wireless extensions; - currently, this can be used only for non-WPA IEEE 802.1X mode, but - eventually, this is to be extended to support full WPA/WPA2 once - Linux wireless extensions get support for this - * added support for mode in which the driver is responsible for AP - scanning and selection; this is disabled by default and can be - enabled with global ap_scan=0 variable in wpa_supplicant.conf; - this mode can be used, e.g., with generic 'wext' driver interface to - use wpa_supplicant as IEEE 802.1X Supplicant with any Linux driver - supporting wireless extensions. - * driver_madwifi: fixed WPA2 configuration and scan_ssid=1 (e.g., - operation with an AP that does not include SSID in the Beacon frames) - * added support for new EAP authentication methods: - EAP-TTLS/EAP-OTP, EAP-PEAPv0/OTP, EAP-PEAPv1/OTP, EAP-OTP - * added support for asking one-time-passwords from frontends (e.g., - wpa_cli); this 'otp' command works otherwise like 'password' command, - but the password is used only once and the frontend will be asked for - a new password whenever a request from authenticator requires a - password; this can be used with both EAP-OTP and EAP-GTC - * changed wpa_cli to automatically re-establish connection so that it - does not need to be re-started when wpa_supplicant is terminated and - started again - * improved user data (identity/password/otp) requests through - frontends: process pending EAPOL packets after getting new - information so that full authentication does not need to be - restarted; in addition, send pending requests again whenever a new - frontend is attached - * changed control frontends to use a new directory for socket files to - make it easier for wpa_cli to automatically select between interfaces - and to provide access control for the control interface; - wpa_supplicant.conf: ctrl_interface is now a path - (/var/run/wpa_supplicant is the recommended path) and - ctrl_interface_group can be used to select which group gets access to - the control interface; - wpa_cli: by default, try to connect to the first interface available - in /var/run/wpa_supplicant; this path can be overriden with -p option - and an interface can be selected with -i option (i.e., in most common - cases, wpa_cli does not need to get any arguments) - * added support for LEAP - * added driver interface for Linux ndiswrapper - * added priority option for network blocks in the configuration file; - this allows networks to be grouped based on priority (the scan - results are searched for matches with network blocks in this order) - -2004-06-20 - v0.2.3 - * sort scan results to improve AP selection - * fixed control interface socket removal for some error cases - * improved scan requesting and authentication timeout - * small improvements/bug fixes for EAP-MSCHAPv2, EAP-PEAP, and - TLS processing - * PEAP version can now be forced with phase1="peapver=<ver>" - (mostly for testing; by default, the highest version supported by - both the Supplicant and Authentication Server is selected - automatically) - * added support for madwifi driver (Atheros ar521x) - * added a workaround for cases where AP sets Install Tx/Rx bit for - WPA Group Key messages when pairwise keys are used (without this, - the Group Key would be used for Tx and the AP would drop frames - from the station) - * added GSM SIM/USIM interface for GSM authentication algorithm for - EAP-SIM; this requires pcsc-lite - * added support for ATMEL AT76C5XXx driver - * fixed IEEE 802.1X WEP key derivation in the case where Authenticator - does not include key data in the EAPOL-Key frame (i.e., part of - EAP keying material is used as data encryption key) - * added support for using plaintext and static WEP networks - (key_mgmt=NONE) - -2004-05-31 - v0.2.2 - * added support for new EAP authentication methods: - EAP-TTLS/EAP-MD5-Challenge - EAP-TTLS/EAP-GTC - EAP-TTLS/EAP-MSCHAPv2 - EAP-TTLS/EAP-TLS - EAP-TTLS/MSCHAPv2 - EAP-TTLS/MSCHAP - EAP-TTLS/PAP - EAP-TTLS/CHAP - EAP-PEAP/TLS - EAP-PEAP/GTC - EAP-PEAP/MD5-Challenge - EAP-GTC - EAP-SIM (not yet complete; needs GSM/SIM authentication interface) - * added support for anonymous identity (to be used when identity is - sent in plaintext; real identity will be used within TLS protected - tunnel (e.g., with EAP-TTLS) - * added event messages from wpa_supplicant to frontends, e.g., wpa_cli - * added support for requesting identity and password information using - control interface; in other words, the password for EAP-PEAP or - EAP-TTLS does not need to be included in the configuration file since - a frontand (e.g., wpa_cli) can ask it from the user - * improved RSN pre-authentication to use a candidate list and process - all candidates from each scan; not only one per scan - * fixed RSN IE and WPA IE capabilities field parsing - * ignore Tx bit in GTK IE when Pairwise keys are used - * avoid making new scan requests during IEEE 802.1X negotiation - * use openssl/libcrypto for MD5 and SHA-1 when compiling wpa_supplicant - with TLS support (this replaces the included implementation with - library code to save about 8 kB since the library code is needed - anyway for TLS) - * fixed WPA-PSK only mode when compiled without IEEE 802.1X support - (i.e., without CONFIG_IEEE8021X_EAPOL=y in .config) - -2004-05-06 - v0.2.1 - * added support for internal IEEE 802.1X (actually, IEEE 802.1aa/D6.1) - Supplicant - - EAPOL state machines for Supplicant [IEEE 802.1aa/D6.1] - - EAP peer state machine [draft-ietf-eap-statemachine-02.pdf] - - EAP-MD5 (cannot be used with WPA-RADIUS) - [draft-ietf-eap-rfc2284bis-09.txt] - - EAP-TLS [RFC 2716] - - EAP-MSCHAPv2 (currently used only with EAP-PEAP) - - EAP-PEAP/MSCHAPv2 [draft-josefsson-pppext-eap-tls-eap-07.txt] - [draft-kamath-pppext-eap-mschapv2-00.txt] - (PEAP version 0, 1, and parts of 2; only 0 and 1 are enabled by - default; tested with FreeRADIUS, Microsoft IAS, and Funk Odyssey) - - new configuration file options: eap, identity, password, ca_cert, - client_cert, privatekey, private_key_passwd - - Xsupplicant is not required anymore, but it can be used by - disabling the internal IEEE 802.1X Supplicant with -e command line - option - - this code is not included in the default build; Makefile need to - be edited for this (uncomment lines for selected functionality) - - EAP-TLS and EAP-PEAP require openssl libraries - * use module prefix in debug messages (WPA, EAP, EAP-TLS, ..) - * added support for non-WPA IEEE 802.1X mode with dynamic WEP keys - (i.e., complete IEEE 802.1X/EAP authentication and use IEEE 802.1X - EAPOL-Key frames instead of WPA key handshakes) - * added support for IEEE 802.11i/RSN (WPA2) - - improved PTK Key Handshake - - PMKSA caching, pre-authentication - * fixed wpa_supplicant to ignore possible extra data after WPA - EAPOL-Key packets (this fixes 'Invalid EAPOL-Key MIC when using - TPTK' error from message 3 of 4-Way Handshake in case the AP - includes extra data after the EAPOL-Key) - * added interface for external programs (frontends) to control - wpa_supplicant - - CLI example (wpa_cli) with interactive mode and command line - mode - - replaced SIGUSR1 status/statistics with the new control interface - * made some feature compile time configurable - - .config file for make - - driver interfaces (hostap, hermes, ..) - - EAPOL/EAP functions - -2004-02-15 - v0.2.0 - * Initial version of wpa_supplicant diff --git a/contrib/wpa_supplicant/FREEBSD-Xlist b/contrib/wpa_supplicant/FREEBSD-Xlist deleted file mode 100644 index da2934b13085..000000000000 --- a/contrib/wpa_supplicant/FREEBSD-Xlist +++ /dev/null @@ -1,37 +0,0 @@ -$FreeBSD$ -.cvsignore -README-Windows.txt -config_winreg.c -ctrl_iface_named_pipe.c -driver_atmel.c -driver_broadcom.c -driver_bsd.c -driver_hostap.c -driver_hostap.h -driver_ipw.c -driver_madwifi.c -driver_ndiswrapper.c -driver_ndis_.c -driver_prism54.c -driver_test.c -driver_wext.c -driver_wext.h -eloop_win.c -l2_packet_freebsd.c -l2_packet_linux.c -l2_packet_ndis.c -l2_packet_none.c -l2_packet_pcap.c -l2_packet_winpcap.c -main_none.c -main_winmain.c -main_winsvc.c -ndis_events.c -ndis_events.cpp -nmake.mk -os_win32.c -priv_netlink.h -vs2005 -win_example.reg -win_if_list.c -wireless_copy.h diff --git a/contrib/wpa_supplicant/FREEBSD-upgrade b/contrib/wpa_supplicant/FREEBSD-upgrade deleted file mode 100644 index dfb149e0ba18..000000000000 --- a/contrib/wpa_supplicant/FREEBSD-upgrade +++ /dev/null @@ -1,24 +0,0 @@ -$FreeBSD$ - -WPA Supplicant - originals can be found at: http://hostap.epitest.fi/releases/ - - -For the import files and directories were pruned by: - - tar -X FREEBSD-Xlist -zxf wpa_supplicant-0.5.10.tar.gz - -then imported by: - - cvs import -m 'Import of WPA supplicant 0.5.10' \ - src/contrib/wpa_supplicant MALINEN v0_5_10 - -To make local changes to wpa_supplcaint, simply patch and commit -to the main branch (aka HEAD). Never make local changes on the -vendor (MALINEN) branch. - -All local changes should be submitted to Jouni Malinen for inclusion in -the next vendor release. - -sam@FreeBSD.org -24-March-2008 diff --git a/contrib/wpa_supplicant/Makefile b/contrib/wpa_supplicant/Makefile deleted file mode 100644 index 74ea2f59281a..000000000000 --- a/contrib/wpa_supplicant/Makefile +++ /dev/null @@ -1,921 +0,0 @@ -ifndef CC -CC=gcc -endif - -ifndef CFLAGS -CFLAGS = -MMD -O2 -Wall -g -endif - -# Include directories for CVS version -CFLAGS += -I. -I../utils -I../hostapd - -ALL=wpa_supplicant wpa_passphrase wpa_cli - -all: verify_config $(ALL) dynamic_eap_methods - -verify_config: - @if [ ! -r .config ]; then \ - echo 'Building wpa_supplicant 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 - -mkconfig: - @if [ -e .config ]; then \ - echo '.config exists - did not replace it'; \ - exit 1; \ - fi - echo CONFIG_DRIVER_HOSTAP=y >> .config - echo CONFIG_DRIVER_WEXT=y >> .config - echo CONFIG_WIRELESS_EXTENSION=y >> .config - -install: all - mkdir -p $(DESTDIR)/usr/local/sbin/ - for i in $(ALL); do cp $$i $(DESTDIR)/usr/local/sbin/$$i; done - -OBJS = config.o \ - common.o md5.o md4.o \ - rc4.o sha1.o des.o -OBJS_p = wpa_passphrase.o sha1.o md5.o md4.o \ - common.o des.o -OBJS_c = wpa_cli.o wpa_ctrl.o - --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 - -OBJS += os_$(CONFIG_OS).o -OBJS_p += os_$(CONFIG_OS).o -OBJS_c += os_$(CONFIG_OS).o - -ifndef CONFIG_ELOOP -CONFIG_ELOOP=eloop -endif -OBJS += $(CONFIG_ELOOP).o - - -ifdef CONFIG_EAPOL_TEST -CFLAGS += -Werror -DEAPOL_TEST -endif - -ifndef CONFIG_BACKEND -CONFIG_BACKEND=file -endif - -ifeq ($(CONFIG_BACKEND), file) -OBJS += config_file.o base64.o -CFLAGS += -DCONFIG_BACKEND_FILE -endif - -ifeq ($(CONFIG_BACKEND), winreg) -OBJS += config_winreg.o -endif - -ifeq ($(CONFIG_BACKEND), none) -OBJS += config_none.o -endif - -ifdef CONFIG_DRIVER_HOSTAP -CFLAGS += -DCONFIG_DRIVER_HOSTAP -OBJS_d += driver_hostap.o -CONFIG_WIRELESS_EXTENSION=y -endif - -ifdef CONFIG_DRIVER_WEXT -CFLAGS += -DCONFIG_DRIVER_WEXT -CONFIG_WIRELESS_EXTENSION=y -endif - -ifdef CONFIG_DRIVER_PRISM54 -CFLAGS += -DCONFIG_DRIVER_PRISM54 -OBJS_d += driver_prism54.o -CONFIG_WIRELESS_EXTENSION=y -endif - -ifdef CONFIG_DRIVER_HERMES -CFLAGS += -DCONFIG_DRIVER_HERMES -OBJS_d += driver_hermes.o -CONFIG_WIRELESS_EXTENSION=y -endif - -ifdef CONFIG_DRIVER_MADWIFI -CFLAGS += -DCONFIG_DRIVER_MADWIFI -OBJS_d += driver_madwifi.o -CONFIG_WIRELESS_EXTENSION=y -endif - -ifdef CONFIG_DRIVER_ATMEL -CFLAGS += -DCONFIG_DRIVER_ATMEL -OBJS_d += driver_atmel.o -CONFIG_WIRELESS_EXTENSION=y -endif - -ifdef CONFIG_DRIVER_NDISWRAPPER -CFLAGS += -DCONFIG_DRIVER_NDISWRAPPER -OBJS_d += driver_ndiswrapper.o -CONFIG_WIRELESS_EXTENSION=y -endif - -ifdef CONFIG_DRIVER_BROADCOM -CFLAGS += -DCONFIG_DRIVER_BROADCOM -OBJS_d += driver_broadcom.o -endif - -ifdef CONFIG_DRIVER_IPW -CFLAGS += -DCONFIG_DRIVER_IPW -OBJS_d += driver_ipw.o -CONFIG_WIRELESS_EXTENSION=y -endif - -ifdef CONFIG_DRIVER_BSD -CFLAGS += -DCONFIG_DRIVER_BSD -OBJS_d += driver_bsd.o -ifndef CONFIG_L2_PACKET -CONFIG_L2_PACKET=freebsd -endif -endif - -ifdef CONFIG_DRIVER_NDIS -CFLAGS += -DCONFIG_DRIVER_NDIS -OBJS_d += driver_ndis.o -ifdef CONFIG_NDIS_EVENTS_INTEGRATED -OBJS_d += driver_ndis_.o -endif -ifndef CONFIG_L2_PACKET -CONFIG_L2_PACKET=pcap -endif -CONFIG_WINPCAP=y -ifdef CONFIG_USE_NDISUIO -CFLAGS += -DCONFIG_USE_NDISUIO -endif -endif - -ifdef CONFIG_DRIVER_WIRED -CFLAGS += -DCONFIG_DRIVER_WIRED -OBJS_d += driver_wired.o -endif - -ifdef CONFIG_DRIVER_TEST -CFLAGS += -DCONFIG_DRIVER_TEST -OBJS_d += driver_test.o -endif - -ifndef CONFIG_L2_PACKET -CONFIG_L2_PACKET=linux -endif - -OBJS += l2_packet_$(CONFIG_L2_PACKET).o - -ifeq ($(CONFIG_L2_PACKET), pcap) -ifdef CONFIG_WINPCAP -CFLAGS += -DCONFIG_WINPCAP -LIBS += -lwpcap -lpacket -LIBS_w += -lwpcap -else -LIBS += -ldnet -lpcap -endif -endif - -ifeq ($(CONFIG_L2_PACKET), winpcap) -LIBS += -lwpcap -lpacket -LIBS_w += -lwpcap -endif - -ifeq ($(CONFIG_L2_PACKET), freebsd) -LIBS += -lpcap -endif - -ifdef CONFIG_EAP_TLS -# EAP-TLS -ifeq ($(CONFIG_EAP_TLS), dyn) -CFLAGS += -DEAP_TLS_DYNAMIC -EAPDYN += eap_tls.so -else -CFLAGS += -DEAP_TLS -OBJS += eap_tls.o -endif -TLS_FUNCS=y -CONFIG_IEEE8021X_EAPOL=y -endif - -ifdef CONFIG_EAP_PEAP -# EAP-PEAP -ifeq ($(CONFIG_EAP_PEAP), dyn) -CFLAGS += -DEAP_PEAP_DYNAMIC -EAPDYN += eap_peap.so -else -CFLAGS += -DEAP_PEAP -OBJS += eap_peap.o -endif -TLS_FUNCS=y -CONFIG_IEEE8021X_EAPOL=y -CONFIG_EAP_TLV=y -endif - -ifdef CONFIG_EAP_TTLS -# EAP-TTLS -ifeq ($(CONFIG_EAP_TTLS), dyn) -CFLAGS += -DEAP_TTLS_DYNAMIC -EAPDYN += eap_ttls.so -else -CFLAGS += -DEAP_TTLS -OBJS += eap_ttls.o -endif -MS_FUNCS=y -TLS_FUNCS=y -CONFIG_IEEE8021X_EAPOL=y -endif - -ifdef CONFIG_EAP_MD5 -# EAP-MD5 -ifeq ($(CONFIG_EAP_MD5), dyn) -CFLAGS += -DEAP_MD5_DYNAMIC -EAPDYN += eap_md5.so -else -CFLAGS += -DEAP_MD5 -OBJS += eap_md5.o -endif -CONFIG_IEEE8021X_EAPOL=y -endif - -# backwards compatibility for old spelling -ifdef CONFIG_MSCHAPV2 -ifndef CONFIG_EAP_MSCHAPV2 -CONFIG_EAP_MSCHAPV2=y -endif -endif - -ifdef CONFIG_EAP_MSCHAPV2 -# EAP-MSCHAPv2 -ifeq ($(CONFIG_EAP_MSCHAPV2), dyn) -CFLAGS += -DEAP_MSCHAPv2_DYNAMIC -EAPDYN += eap_mschapv2.so -else -CFLAGS += -DEAP_MSCHAPv2 -OBJS += eap_mschapv2.o -endif -MS_FUNCS=y -CONFIG_IEEE8021X_EAPOL=y -endif - -ifdef CONFIG_EAP_GTC -# EAP-GTC -ifeq ($(CONFIG_EAP_GTC), dyn) -CFLAGS += -DEAP_GTC_DYNAMIC -EAPDYN += eap_gtc.so -else -CFLAGS += -DEAP_GTC -OBJS += eap_gtc.o -endif -CONFIG_IEEE8021X_EAPOL=y -endif - -ifdef CONFIG_EAP_OTP -# EAP-OTP -ifeq ($(CONFIG_EAP_OTP), dyn) -CFLAGS += -DEAP_OTP_DYNAMIC -EAPDYN += eap_otp.so -else -CFLAGS += -DEAP_OTP -OBJS += eap_otp.o -endif -CONFIG_IEEE8021X_EAPOL=y -endif - -ifdef CONFIG_EAP_SIM -# EAP-SIM -ifeq ($(CONFIG_EAP_SIM), dyn) -CFLAGS += -DEAP_SIM_DYNAMIC -EAPDYN += eap_sim.so -else -CFLAGS += -DEAP_SIM -OBJS += eap_sim.o -endif -CONFIG_IEEE8021X_EAPOL=y -CONFIG_EAP_SIM_COMMON=y -endif - -ifdef CONFIG_EAP_LEAP -# EAP-LEAP -ifeq ($(CONFIG_EAP_LEAP), dyn) -CFLAGS += -DEAP_LEAP_DYNAMIC -EAPDYN += eap_leap.so -else -CFLAGS += -DEAP_LEAP -OBJS += eap_leap.o -endif -MS_FUNCS=y -CONFIG_IEEE8021X_EAPOL=y -endif - -ifdef CONFIG_EAP_PSK -# EAP-PSK -ifeq ($(CONFIG_EAP_PSK), dyn) -CFLAGS += -DEAP_PSK_DYNAMIC -EAPDYN += eap_psk.so -else -CFLAGS += -DEAP_PSK -OBJS += eap_psk.o eap_psk_common.o -endif -CONFIG_IEEE8021X_EAPOL=y -NEED_AES=y -endif - -ifdef CONFIG_EAP_AKA -# EAP-AKA -ifeq ($(CONFIG_EAP_AKA), dyn) -CFLAGS += -DEAP_AKA_DYNAMIC -EAPDYN += eap_aka.so -else -CFLAGS += -DEAP_AKA -OBJS += eap_aka.o -endif -CONFIG_IEEE8021X_EAPOL=y -CONFIG_EAP_SIM_COMMON=y -endif - -ifdef CONFIG_EAP_SIM_COMMON -OBJS += eap_sim_common.o -NEED_AES=y -endif - -ifdef CONFIG_EAP_TLV -# EAP-TLV -CFLAGS += -DEAP_TLV -OBJS += eap_tlv.o -endif - -ifdef CONFIG_EAP_FAST -# EAP-FAST -ifeq ($(CONFIG_EAP_FAST), dyn) -CFLAGS += -DEAP_FAST_DYNAMIC -EAPDYN += eap_fast.so -else -CFLAGS += -DEAP_FAST -OBJS += eap_fast.o -endif -TLS_FUNCS=y -endif - -ifdef CONFIG_EAP_PAX -# EAP-PAX -ifeq ($(CONFIG_EAP_PAX), dyn) -CFLAGS += -DEAP_PAX_DYNAMIC -EAPDYN += eap_pax.so -else -CFLAGS += -DEAP_PAX -OBJS += eap_pax.o eap_pax_common.o -endif -CONFIG_IEEE8021X_EAPOL=y -endif - -ifdef CONFIG_EAP_SAKE -# EAP-SAKE -ifeq ($(CONFIG_EAP_SAKE), dyn) -CFLAGS += -DEAP_SAKE_DYNAMIC -EAPDYN += eap_sake.so -else -CFLAGS += -DEAP_SAKE -OBJS += eap_sake.o eap_sake_common.o -endif -CONFIG_IEEE8021X_EAPOL=y -endif - -ifdef CONFIG_EAP_GPSK -# EAP-GPSK -ifeq ($(CONFIG_EAP_GPSK), dyn) -CFLAGS += -DEAP_GPSK_DYNAMIC -EAPDYN += eap_gpsk.so -else -CFLAGS += -DEAP_GPSK -OBJS += eap_gpsk.o eap_gpsk_common.o -endif -CONFIG_IEEE8021X_EAPOL=y -ifdef CONFIG_EAP_GPSK_SHA256 -CFLAGS += -DEAP_GPSK_SHA256 -NEED_SHA256=y -endif -endif - -ifdef CONFIG_EAP_VENDOR_TEST -ifeq ($(CONFIG_EAP_VENDOR_TEST), dyn) -CFLAGS += -DEAP_VENDOR_TEST_DYNAMIC -EAPDYN += eap_vendor_test.so -else -CFLAGS += -DEAP_VENDOR_TEST -OBJS += eap_vendor_test.o -endif -CONFIG_IEEE8021X_EAPOL=y -endif - -ifdef CONFIG_IEEE8021X_EAPOL -# IEEE 802.1X/EAPOL state machines (e.g., for RADIUS authentication) -CFLAGS += -DIEEE8021X_EAPOL -OBJS += eapol_sm.o eap.o eap_methods.o -ifdef CONFIG_DYNAMIC_EAP_METHODS -CFLAGS += -DCONFIG_DYNAMIC_EAP_METHODS -LIBS += -ldl -rdynamic -endif -endif - -ifdef CONFIG_PCSC -# PC/SC interface for smartcards (USIM, GSM SIM) -CFLAGS += -DPCSC_FUNCS -I/usr/include/PCSC -OBJS += pcsc_funcs.o -# -lpthread may not be needed depending on how pcsc-lite was configured -ifdef CONFIG_NATIVE_WINDOWS -#Once MinGW gets support for WinScard, -lwinscard could be used instead of the -#dynamic symbol loading that is now used in pcsc_funcs.c -#LIBS += -lwinscard -else -LIBS += -lpcsclite -lpthread -endif -endif - -ifndef CONFIG_TLS -CONFIG_TLS=openssl -endif - -ifeq ($(CONFIG_TLS), internal) -ifndef CONFIG_CRYPTO -CONFIG_CRYPTO=internal -endif -endif -ifeq ($(CONFIG_CRYPTO), libtomcrypt) -CFLAGS += -DCONFIG_INTERNAL_X509 -endif -ifeq ($(CONFIG_CRYPTO), internal) -CFLAGS += -DCONFIG_INTERNAL_X509 -endif - - -ifdef TLS_FUNCS -# Shared TLS functions (needed for EAP_TLS, EAP_PEAP, EAP_TTLS, and EAP_FAST) -CFLAGS += -DEAP_TLS_FUNCS -OBJS += eap_tls_common.o -ifeq ($(CONFIG_TLS), openssl) -CFLAGS += -DEAP_TLS_OPENSSL -OBJS += tls_openssl.o -LIBS += -lssl -lcrypto -LIBS_p += -lcrypto -endif -ifeq ($(CONFIG_TLS), gnutls) -OBJS += tls_gnutls.o -LIBS += -lgnutls -lgcrypt -lgpg-error -LIBS_p += -lgcrypt -ifdef CONFIG_GNUTLS_EXTRA -CFLAGS += -DCONFIG_GNUTLS_EXTRA -LIBS += -lgnutls-extra -endif -endif -ifeq ($(CONFIG_TLS), schannel) -OBJS += tls_schannel.o -endif -ifeq ($(CONFIG_TLS), internal) -OBJS += tls_internal.o tlsv1_common.o tlsv1_client.o asn1.o x509v3.o -OBJS_p += asn1.o rc4.o aes_wrap.o -ifneq ($(CONFIG_BACKEND), file) -OBJS += base64.o -endif -CFLAGS += -DCONFIG_TLS_INTERNAL -ifeq ($(CONFIG_CRYPTO), internal) -ifdef CONFIG_INTERNAL_LIBTOMMATH -CFLAGS += -DCONFIG_INTERNAL_LIBTOMMATH -else -LIBS += -ltommath -LIBS_p += -ltommath -endif -endif -ifeq ($(CONFIG_CRYPTO), libtomcrypt) -LIBS += -ltomcrypt -ltfm -LIBS_p += -ltomcrypt -ltfm -endif -endif -ifeq ($(CONFIG_TLS), none) -OBJS += tls_none.o -CFLAGS += -DEAP_TLS_NONE -CONFIG_INTERNAL_AES=y -CONFIG_INTERNAL_SHA1=y -CONFIG_INTERNAL_MD5=y -CONFIG_INTERNAL_SHA256=y -endif -ifdef CONFIG_SMARTCARD -ifndef CONFIG_NATIVE_WINDOWS -ifneq ($(CONFIG_L2_PACKET), freebsd) -LIBS += -ldl -endif -endif -endif -NEED_CRYPTO=y -else -OBJS += tls_none.o -endif - -ifdef CONFIG_PKCS12 -CFLAGS += -DPKCS12_FUNCS -endif - -ifdef CONFIG_SMARTCARD -CFLAGS += -DCONFIG_SMARTCARD -endif - -ifdef MS_FUNCS -OBJS += ms_funcs.o -NEED_CRYPTO=y -endif - -ifdef NEED_CRYPTO -ifndef TLS_FUNCS -ifeq ($(CONFIG_TLS), openssl) -LIBS += -lcrypto -LIBS_p += -lcrypto -endif -ifeq ($(CONFIG_TLS), gnutls) -LIBS += -lgcrypt -LIBS_p += -lgcrypt -endif -ifeq ($(CONFIG_TLS), schannel) -endif -ifeq ($(CONFIG_TLS), internal) -ifeq ($(CONFIG_CRYPTO), libtomcrypt) -LIBS += -ltomcrypt -ltfm -LIBS_p += -ltomcrypt -ltfm -endif -endif -endif -ifeq ($(CONFIG_TLS), openssl) -OBJS += crypto.o -OBJS_p += crypto.o -CONFIG_INTERNAL_SHA256=y -endif -ifeq ($(CONFIG_TLS), gnutls) -OBJS += crypto_gnutls.o -OBJS_p += crypto_gnutls.o -CONFIG_INTERNAL_SHA256=y -endif -ifeq ($(CONFIG_TLS), schannel) -OBJS += crypto_cryptoapi.o -OBJS_p += crypto_cryptoapi.o -CONFIG_INTERNAL_SHA256=y -endif -ifeq ($(CONFIG_TLS), internal) -ifeq ($(CONFIG_CRYPTO), libtomcrypt) -OBJS += crypto_libtomcrypt.o -OBJS_p += crypto_libtomcrypt.o -CONFIG_INTERNAL_SHA256=y -endif -ifeq ($(CONFIG_CRYPTO), internal) -OBJS += crypto_internal.o rsa.o bignum.o -OBJS_p += crypto_internal.o rsa.o bignum.o -CFLAGS += -DCONFIG_CRYPTO_INTERNAL -CONFIG_INTERNAL_AES=y -CONFIG_INTERNAL_DES=y -CONFIG_INTERNAL_SHA1=y -CONFIG_INTERNAL_MD4=y -CONFIG_INTERNAL_MD5=y -CONFIG_INTERNAL_SHA256=y -endif -ifeq ($(CONFIG_CRYPTO), cryptoapi) -OBJS += crypto_cryptoapi.o -OBJS_p += crypto_cryptoapi.o -CFLAGS += -DCONFIG_CRYPTO_CRYPTOAPI -CONFIG_INTERNAL_SHA256=y -endif -endif -ifeq ($(CONFIG_TLS), none) -OBJS += crypto_none.o -OBJS_p += crypto_none.o -CONFIG_INTERNAL_SHA256=y -endif -else -CONFIG_INTERNAL_AES=y -CONFIG_INTERNAL_SHA1=y -CONFIG_INTERNAL_MD5=y -endif - -ifdef CONFIG_INTERNAL_AES -CFLAGS += -DINTERNAL_AES -endif -ifdef CONFIG_INTERNAL_SHA1 -CFLAGS += -DINTERNAL_SHA1 -endif -ifdef CONFIG_INTERNAL_SHA256 -CFLAGS += -DINTERNAL_SHA256 -endif -ifdef CONFIG_INTERNAL_MD5 -CFLAGS += -DINTERNAL_MD5 -endif -ifdef CONFIG_INTERNAL_MD4 -CFLAGS += -DINTERNAL_MD4 -endif -ifdef CONFIG_INTERNAL_DES -CFLAGS += -DINTERNAL_DES -endif - -ifdef NEED_SHA256 -OBJS += sha256.o -endif - -ifdef CONFIG_WIRELESS_EXTENSION -CFLAGS += -DCONFIG_WIRELESS_EXTENSION -OBJS_d += driver_wext.o -endif - -ifdef CONFIG_CTRL_IFACE -ifeq ($(CONFIG_CTRL_IFACE), y) -ifdef CONFIG_NATIVE_WINDOWS -CONFIG_CTRL_IFACE=named_pipe -else -CONFIG_CTRL_IFACE=unix -endif -endif -CFLAGS += -DCONFIG_CTRL_IFACE -ifeq ($(CONFIG_CTRL_IFACE), unix) -CFLAGS += -DCONFIG_CTRL_IFACE_UNIX -endif -ifeq ($(CONFIG_CTRL_IFACE), udp) -CFLAGS += -DCONFIG_CTRL_IFACE_UDP -endif -ifeq ($(CONFIG_CTRL_IFACE), named_pipe) -CFLAGS += -DCONFIG_CTRL_IFACE_NAMED_PIPE -endif -OBJS += ctrl_iface.o ctrl_iface_$(CONFIG_CTRL_IFACE).o -endif - -ifdef CONFIG_CTRL_IFACE_DBUS -CFLAGS += -DCONFIG_CTRL_IFACE_DBUS -DDBUS_API_SUBJECT_TO_CHANGE -OBJS += ctrl_iface_dbus.o ctrl_iface_dbus_handlers.o dbus_dict_helpers.o -ifndef DBUS_LIBS -DBUS_LIBS := $(shell pkg-config --libs dbus-1) -endif -LIBS += $(DBUS_LIBS) -ifndef DBUS_INCLUDE -DBUS_INCLUDE := $(shell pkg-config --cflags dbus-1) -endif -dbus_version=$(subst ., ,$(shell pkg-config --modversion dbus-1)) -DBUS_VERSION_MAJOR=$(word 1,$(dbus_version)) -DBUS_VERSION_MINOR=$(word 2,$(dbus_version)) -ifeq ($(DBUS_VERSION_MAJOR),) -DBUS_VERSION_MAJOR=0 -endif -ifeq ($(DBUS_VERSION_MINOR),) -DBUS_VERSION_MINOR=0 -endif -DBUS_INCLUDE += -DDBUS_VERSION_MAJOR=$(DBUS_VERSION_MAJOR) -DBUS_INCLUDE += -DDBUS_VERSION_MINOR=$(DBUS_VERSION_MINOR) -CFLAGS += $(DBUS_INCLUDE) -endif - -ifdef CONFIG_READLINE -CFLAGS += -DCONFIG_READLINE -LIBS_c += -lncurses -lreadline -endif - -ifdef CONFIG_NATIVE_WINDOWS -CFLAGS += -DCONFIG_NATIVE_WINDOWS -LIBS += -lws2_32 -lgdi32 -lcrypt32 -LIBS_c += -lws2_32 -LIBS_p += -lws2_32 -ifeq ($(CONFIG_CRYPTO), cryptoapi) -LIBS_p += -lcrypt32 -endif -endif - -ifdef CONFIG_NO_STDOUT_DEBUG -CFLAGS += -DCONFIG_NO_STDOUT_DEBUG -ifndef CONFIG_CTRL_IFACE -CFLAGS += -DCONFIG_NO_WPA_MSG -endif -endif - -ifdef CONFIG_IPV6 -# for eapol_test only -CFLAGS += -DCONFIG_IPV6 -endif - -ifdef CONFIG_PEERKEY -CFLAGS += -DCONFIG_PEERKEY -endif - -ifdef CONFIG_IEEE80211W -CFLAGS += -DCONFIG_IEEE80211W -NEED_SHA256=y -endif - -ifndef CONFIG_NO_WPA -OBJS += wpa.o preauth.o pmksa_cache.o -NEED_AES=y -else -CFLAGS += -DCONFIG_NO_WPA -DCONFIG_NO_WPA2 -endif - -ifdef CONFIG_NO_WPA2 -CFLAGS += -DCONFIG_NO_WPA2 -endif - -ifdef CONFIG_NO_AES_EXTRAS -CFLAGS += -DCONFIG_NO_AES_WRAP -CFLAGS += -DCONFIG_NO_AES_CTR -DCONFIG_NO_AES_OMAC1 -CFLAGS += -DCONFIG_NO_AES_EAX -DCONFIG_NO_AES_CBC -endif - -ifdef NEED_AES -OBJS += aes_wrap.o -endif - -ifdef CONFIG_CLIENT_MLME -OBJS += mlme.o -CFLAGS += -DCONFIG_CLIENT_MLME -endif - -ifndef CONFIG_MAIN -CONFIG_MAIN=main -endif - -ifdef CONFIG_DEBUG_FILE -CFLAGS += -DCONFIG_DEBUG_FILE -endif - -ifdef CONFIG_DEBUG_SYSLOG -CFLAGS += -DCONFIG_DEBUG_SYSLOG -endif - -OBJS += wpa_supplicant.o events.o -OBJS_t := $(OBJS) eapol_test.o radius.o radius_client.o -OBJS_t2 := $(OBJS) preauth_test.o -OBJS += $(CONFIG_MAIN).o drivers.o $(OBJS_d) - -ifdef CONFIG_NDIS_EVENTS_INTEGRATED -CFLAGS += -DCONFIG_NDIS_EVENTS_INTEGRATED -OBJS += ndis_events.o -EXTRALIBS += -loleaut32 -lole32 -luuid -ifdef PLATFORMSDKLIB -EXTRALIBS += $(PLATFORMSDKLIB)/WbemUuid.Lib -else -EXTRALIBS += WbemUuid.Lib -endif -endif - -ifndef LDO -LDO=$(CC) -endif - -dynamic_eap_methods: $(EAPDYN) - -wpa_supplicant: .config $(OBJS) - $(LDO) $(LDFLAGS) -o wpa_supplicant $(OBJS) $(LIBS) $(EXTRALIBS) - -eapol_test: .config $(OBJS_t) - $(LDO) $(LDFLAGS) -o eapol_test $(OBJS_t) $(LIBS) - -preauth_test: .config $(OBJS_t2) - $(LDO) $(LDFLAGS) -o preauth_test $(OBJS_t2) $(LIBS) - -wpa_passphrase: $(OBJS_p) - $(LDO) $(LDFLAGS) -o wpa_passphrase $(OBJS_p) $(LIBS_p) - -wpa_cli: $(OBJS_c) - $(LDO) $(LDFLAGS) -o wpa_cli $(OBJS_c) $(LIBS_c) - -OBJSa=asn1_test.o asn1.o x509v3.o common.o os_unix.o \ - crypto_$(CONFIG_CRYPTO).o md5.o sha1.o \ - rc4.o des.o aes_wrap.o \ - bignum.o rsa.o -asn1_test: $(OBJSa) - $(LDO) $(LDFLAGS) -o asn1_test $(OBJSa) - -OBJSx=tests/test_x509v3.o asn1.o x509v3.o \ - common.o os_unix.o \ - crypto_$(CONFIG_CRYPTO).o \ - md5.o sha1.o \ - rc4.o des.o aes_wrap.o \ - bignum.o rsa.o -test_x509v3: $(OBJSx) - $(LDO) $(LDFLAGS) -o test_x509v3 $(OBJSx) - -win_if_list: win_if_list.c - $(LDO) $(LDFLAGS) -o $@ win_if_list.c $(CFLAGS) $(LIBS_w) - -eap_psk.so: eap_psk.c eap_psk_common.c - $(CC) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \ - -Deap_peer_psk_register=eap_peer_method_dynamic_init - -eap_pax.so: eap_pax.c eap_pax_common.c - $(CC) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \ - -Deap_peer_pax_register=eap_peer_method_dynamic_init - -eap_sake.so: eap_sake.c eap_sake_common.c - $(CC) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $^ \ - -Deap_peer_sake_register=eap_peer_method_dynamic_init - -%.so: %.c - $(CC) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $< \ - -D$(*:eap_%=eap_peer_%)_register=eap_peer_method_dynamic_init - - -wpa_supplicant.exe: wpa_supplicant - mv -f $< $@ -wpa_cli.exe: wpa_cli - mv -f $< $@ -wpa_passphrase.exe: wpa_passphrase - mv -f $< $@ -win_if_list.exe: win_if_list - mv -f $< $@ -eapol_test.exe: eapol_test - mv -f $< $@ - -WINALL=wpa_supplicant.exe wpa_cli.exe wpa_passphrase.exe win_if_list.exe - -windows-bin: $(WINALL) - $(STRIP) $(WINALL) - -wpa_gui/Makefile: - qmake -o wpa_gui/Makefile wpa_gui/wpa_gui.pro - -wpa_gui: wpa_gui/Makefile - $(MAKE) -C wpa_gui - -TEST_MS_FUNCS_OBJS = crypto.o sha1.o md5.o \ - os_unix.o rc4.o tests/test_ms_funcs.o -test-ms_funcs: $(TEST_MS_FUNCS_OBJS) - $(LDO) $(LDFLAGS) -o $@ $(TEST_MS_FUNCS_OBJS) $(LIBS) -lcrypto - ./test-ms_funcs - rm test-ms_funcs - -TEST_SHA1_OBJS = sha1.o md5.o tests/test_sha1.o #crypto.o -test-sha1: $(TEST_SHA1_OBJS) - $(LDO) $(LDFLAGS) -o $@ $(TEST_SHA1_OBJS) $(LIBS) - ./test-sha1 - rm test-sha1 - -TEST_SHA256_OBJS = sha256.o md5.o tests/test_sha256.o crypto.o -test-sha256: $(TEST_SHA256_OBJS) - $(LDO) $(LDFLAGS) -o $@ $(TEST_SHA256_OBJS) $(LIBS) - ./test-sha256 - rm test-sha256 - -TEST_AES_OBJS = aes_wrap.o tests/test_aes.o # crypto.o -test-aes: $(TEST_AES_OBJS) - $(LDO) $(LDFLAGS) -o $@ $(TEST_AES_OBJS) $(LIBS) - ./test-aes - rm test-aes - -TEST_EAP_SIM_COMMON_OBJS = sha1.o md5.o \ - aes_wrap.o common.o os_unix.o \ - tests/test_eap_sim_common.o -test-eap_sim_common: $(TEST_EAP_SIM_COMMON_OBJS) - $(LDO) $(LDFLAGS) -o $@ $(TEST_AES_OBJS) $(LIBS) - ./test-eap_sim_common - rm test-eap_sim_common - -TEST_MD4_OBJS = md4.o tests/test_md4.o #crypto.o -test-md4: $(TEST_MD4_OBJS) - $(LDO) $(LDFLAGS) -o $@ $(TEST_MD4_OBJS) $(LIBS) - ./test-md4 - rm test-md4 - -TEST_MD5_OBJS = md5.o tests/test_md5.o #crypto.o -test-md5: $(TEST_MD5_OBJS) - $(LDO) $(LDFLAGS) -o $@ $(TEST_MD5_OBJS) $(LIBS) - ./test-md5 - rm test-md5 - -tests: test-ms_funcs test-sha1 test-aes test-eap_sim_common test-md4 test-md5 - -clean: - rm -f core *~ *.o *.d eap_*.so $(ALL) $(WINALL) - -%.eps: %.fig - fig2dev -L eps $*.fig $*.eps - -%.png: %.fig - fig2dev -L png -m 3 $*.fig | pngtopnm | pnmscale 0.4 | pnmtopng \ - > $*.png - -docs-pics: doc/wpa_supplicant.png doc/wpa_supplicant.eps - -docs: docs-pics - doxygen doc/doxygen.full - $(MAKE) -C doc/latex - cp doc/latex/refman.pdf wpa_supplicant-devel.pdf - -docs-fast: docs-pics - doxygen doc/doxygen.fast - -clean-docs: - rm -rf doc/latex doc/html - rm -f doc/wpa_supplicant.{eps,png} wpa_supplicant-devel.pdf - --include $(OBJS:%.o=%.d) diff --git a/contrib/wpa_supplicant/README b/contrib/wpa_supplicant/README deleted file mode 100644 index 0b3c5858c43e..000000000000 --- a/contrib/wpa_supplicant/README +++ /dev/null @@ -1,970 +0,0 @@ -WPA Supplicant -============== - -Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi> 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. - - - -Features --------- - -Supported WPA/IEEE 802.11i features: -- WPA-PSK ("WPA-Personal") -- WPA with EAP (e.g., with RADIUS authentication server) ("WPA-Enterprise") - Following authentication methods are supported with an integrate IEEE 802.1X - Supplicant: - * EAP-TLS - * EAP-PEAP/MSCHAPv2 (both PEAPv0 and PEAPv1) - * EAP-PEAP/TLS (both PEAPv0 and PEAPv1) - * EAP-PEAP/GTC (both PEAPv0 and PEAPv1) - * EAP-PEAP/OTP (both PEAPv0 and PEAPv1) - * EAP-PEAP/MD5-Challenge (both PEAPv0 and PEAPv1) - * EAP-TTLS/EAP-MD5-Challenge - * EAP-TTLS/EAP-GTC - * EAP-TTLS/EAP-OTP - * EAP-TTLS/EAP-MSCHAPv2 - * EAP-TTLS/EAP-TLS - * EAP-TTLS/MSCHAPv2 - * EAP-TTLS/MSCHAP - * EAP-TTLS/PAP - * EAP-TTLS/CHAP - * EAP-SIM - * EAP-AKA - * EAP-PSK - * EAP-PAX - * EAP-SAKE - * EAP-GPSK - * LEAP (note: requires special support from the driver for IEEE 802.11 - authentication) - (following methods are supported, but since they do not generate keying - material, they cannot be used with WPA or IEEE 802.1X WEP keying) - * EAP-MD5-Challenge - * EAP-MSCHAPv2 - * EAP-GTC - * EAP-OTP -- key management for CCMP, TKIP, WEP104, WEP40 -- RSN/WPA2 (IEEE 802.11i) - * pre-authentication - * PMKSA caching - -Supported TLS/crypto libraries: -- OpenSSL (default) -- GnuTLS - -Internal TLS/crypto implementation (optional): -- can be used in place of an external TLS/crypto library -- TLSv1 -- X.509 certificate processing -- PKCS #1 -- ASN.1 -- RSA -- bignum -- minimal size (ca. 50 kB binary, parts of which are already needed for WPA; - TLSv1/X.509/ASN.1/RSA/bignum parts are about 25 kB on x86) - - -Requirements ------------- - -Current hardware/software requirements: -- Linux kernel 2.4.x or 2.6.x with Linux Wireless Extensions v15 or newer -- FreeBSD 6-CURRENT -- NetBSD-current -- Microsoft Windows with WinPcap (at least WinXP, may work with other versions) -- drivers: - Linux drivers that support WPA/WPA2 configuration with the generic - Linux wireless extensions (WE-18 or newer). Even though there are - number of driver specific interface included in wpa_supplicant, please - note that Linux drivers are moving to use generic wireless extensions - and driver_wext (-Dwext on wpa_supplicant command line) should be the - default option to start with before falling back to driver specific - interface. - - Host AP driver for Prism2/2.5/3 (development snapshot/v0.2.x) - (http://hostap.epitest.fi/) - Driver need to be set in Managed mode ('iwconfig wlan0 mode managed'). - Please note that station firmware version needs to be 1.7.0 or newer - to work in WPA mode. - - Linuxant DriverLoader (http://www.linuxant.com/driverloader/) - with Windows NDIS driver for your wlan card supporting WPA. - - Agere Systems Inc. Linux Driver - (http://www.agere.com/support/drivers/) - Please note that the driver interface file (driver_hermes.c) and - hardware specific include files are not included in the - wpa_supplicant distribution. You will need to copy these from the - source package of the Agere driver. - - madwifi driver for cards based on Atheros chip set (ar521x) - (http://sourceforge.net/projects/madwifi/) - Please note that you will need to modify the wpa_supplicant .config - file to use the correct path for the madwifi driver root directory - (CFLAGS += -I../madwifi/wpa line in example defconfig). - - ATMEL AT76C5XXx driver for USB and PCMCIA cards - (http://atmelwlandriver.sourceforge.net/). - - Linux ndiswrapper (http://ndiswrapper.sourceforge.net/) with - Windows NDIS driver. - - Broadcom wl.o driver - This is a generic Linux driver for Broadcom IEEE 802.11a/g cards. - However, it is proprietary driver that is not publicly available - except for couple of exceptions, mainly Broadcom-based APs/wireless - routers that use Linux. The driver binary can be downloaded, e.g., - from Linksys support site (http://www.linksys.com/support/gpl.asp) - for Linksys WRT54G. The GPL tarball includes cross-compiler and - the needed header file, wlioctl.h, for compiling wpa_supplicant. - This driver support in wpa_supplicant is expected to work also with - other devices based on Broadcom driver (assuming the driver includes - client mode support). - - Intel ipw2100 driver - (http://sourceforge.net/projects/ipw2100/) - - Intel ipw2200 driver - (http://sourceforge.net/projects/ipw2200/) - - In theory, any driver that supports Linux wireless extensions can be - used with IEEE 802.1X (i.e., not WPA) when using ap_scan=0 option in - configuration file. - - Wired Ethernet drivers (with ap_scan=0) - - BSD net80211 layer (e.g., Atheros driver) - At the moment, this is for FreeBSD 6-CURRENT branch and NetBSD-current. - - Windows NDIS - The current Windows port requires WinPcap (http://winpcap.polito.it/). - See README-Windows.txt for more information. - -wpa_supplicant was designed to be portable for different drivers and -operating systems. Hopefully, support for more wlan cards and OSes will be -added in the future. See developer's documentation -(http://hostap.epitest.fi/wpa_supplicant/devel/) for more information about the -design of wpa_supplicant and porting to other drivers. One main goal -is to add full WPA/WPA2 support to Linux wireless extensions to allow -new drivers to be supported without having to implement new -driver-specific interface code in wpa_supplicant. - -Optional libraries for layer2 packet processing: -- libpcap (tested with 0.7.2, most relatively recent versions assumed to work, - this is likely to be available with most distributions, - http://tcpdump.org/) -- libdnet (tested with v1.4, most versions assumed to work, - http://libdnet.sourceforge.net/) - -These libraries are _not_ used in the default Linux build. Instead, -internal Linux specific implementation is used. libpcap/libdnet are -more portable and they can be used by adding CONFIG_L2_PACKET=pcap into -.config. They may also be selected automatically for other operating -systems. In case of Windows builds, WinPcap is used by default -(CONFIG_L2_PACKET=winpcap). - - -Optional libraries for EAP-TLS, EAP-PEAP, and EAP-TTLS: -- OpenSSL (tested with 0.9.7c and 0.9.7d, and 0.9.8 versions; assumed to - work with most relatively recent versions; this is likely to be - available with most distributions, http://www.openssl.org/) -- GnuTLS -- internal TLSv1 implementation - -TLS options for EAP-FAST: -- OpenSSL 0.9.8d _with_ openssl-0.9.8d-tls-extensions.patch applied - (i.e., the default OpenSSL package does not include support for - extensions needed for EAP-FAST) -- internal TLSv1 implementation - -One of these libraries is needed when EAP-TLS, EAP-PEAP, EAP-TTLS, or -EAP-FAST support is enabled. WPA-PSK mode does not require this or EAPOL/EAP -implementation. A configuration file, .config, for compilation is -needed to enable IEEE 802.1X/EAPOL and EAP methods. Note that EAP-MD5, -EAP-GTC, EAP-OTP, and EAP-MSCHAPV2 cannot be used alone with WPA, so -they should only be enabled if testing the EAPOL/EAP state -machines. However, there can be used as inner authentication -algorithms with EAP-PEAP and EAP-TTLS. - -See Building and installing section below for more detailed -information about the wpa_supplicant build time configuration. - - - -WPA ---- - -The original security mechanism of IEEE 802.11 standard was not -designed to be strong and has proven to be insufficient for most -networks that require some kind of security. Task group I (Security) -of IEEE 802.11 working group (http://www.ieee802.org/11/) has worked -to address the flaws of the base standard and has in practice -completed its work in May 2004. The IEEE 802.11i amendment to the IEEE -802.11 standard was approved in June 2004 and published in July 2004. - -Wi-Fi Alliance (http://www.wi-fi.org/) used a draft version of the -IEEE 802.11i work (draft 3.0) to define a subset of the security -enhancements that can be implemented with existing wlan hardware. This -is called Wi-Fi Protected Access<TM> (WPA). This has now become a -mandatory component of interoperability testing and certification done -by Wi-Fi Alliance. Wi-Fi provides information about WPA at its web -site (http://www.wi-fi.org/OpenSection/protected_access.asp). - -IEEE 802.11 standard defined wired equivalent privacy (WEP) algorithm -for protecting wireless networks. WEP uses RC4 with 40-bit keys, -24-bit initialization vector (IV), and CRC32 to protect against packet -forgery. All these choices have proven to be insufficient: key space is -too small against current attacks, RC4 key scheduling is insufficient -(beginning of the pseudorandom stream should be skipped), IV space is -too small and IV reuse makes attacks easier, there is no replay -protection, and non-keyed authentication does not protect against bit -flipping packet data. - -WPA is an intermediate solution for the security issues. It uses -Temporal Key Integrity Protocol (TKIP) to replace WEP. TKIP is a -compromise on strong security and possibility to use existing -hardware. It still uses RC4 for the encryption like WEP, but with -per-packet RC4 keys. In addition, it implements replay protection, -keyed packet authentication mechanism (Michael MIC). - -Keys can be managed using two different mechanisms. WPA can either use -an external authentication server (e.g., RADIUS) and EAP just like -IEEE 802.1X is using or pre-shared keys without need for additional -servers. Wi-Fi calls these "WPA-Enterprise" and "WPA-Personal", -respectively. Both mechanisms will generate a master session key for -the Authenticator (AP) and Supplicant (client station). - -WPA implements a new key handshake (4-Way Handshake and Group Key -Handshake) for generating and exchanging data encryption keys between -the Authenticator and Supplicant. This handshake is also used to -verify that both Authenticator and Supplicant know the master session -key. These handshakes are identical regardless of the selected key -management mechanism (only the method for generating master session -key changes). - - - -IEEE 802.11i / WPA2 -------------------- - -The design for parts of IEEE 802.11i that were not included in WPA has -finished (May 2004) and this amendment to IEEE 802.11 was approved in -June 2004. Wi-Fi Alliance is using the final IEEE 802.11i as a new -version of WPA called WPA2. This includes, e.g., support for more -robust encryption algorithm (CCMP: AES in Counter mode with CBC-MAC) -to replace TKIP and optimizations for handoff (reduced number of -messages in initial key handshake, pre-authentication, and PMKSA caching). - - - -wpa_supplicant --------------- - -wpa_supplicant is an implementation of the WPA Supplicant component, -i.e., the part that runs in the client stations. It implements WPA key -negotiation with a WPA Authenticator and EAP authentication with -Authentication Server. In addition, it controls the roaming and IEEE -802.11 authentication/association of the wlan driver. - -wpa_supplicant is designed to be a "daemon" program that runs in the -background and acts as the backend component controlling the wireless -connection. wpa_supplicant supports separate frontend programs and an -example text-based frontend, wpa_cli, is included with wpa_supplicant. - -Following steps are used when associating with an AP using WPA: - -- wpa_supplicant requests the kernel driver to scan neighboring BSSes -- wpa_supplicant selects a BSS based on its configuration -- wpa_supplicant requests the kernel driver to associate with the chosen - BSS -- If WPA-EAP: integrated IEEE 802.1X Supplicant completes EAP - authentication with the authentication server (proxied by the - Authenticator in the AP) -- If WPA-EAP: master key is received from the IEEE 802.1X Supplicant -- If WPA-PSK: wpa_supplicant uses PSK as the master session key -- wpa_supplicant completes WPA 4-Way Handshake and Group Key Handshake - with the Authenticator (AP) -- wpa_supplicant configures encryption keys for unicast and broadcast -- normal data packets can be transmitted and received - - - -Building and installing ------------------------ - -In order to be able to build wpa_supplicant, you will first need to -select which parts of it will be included. This is done by creating a -build time configuration file, .config, in the wpa_supplicant root -directory. Configuration options are text lines using following -format: CONFIG_<option>=y. Lines starting with # are considered -comments and are ignored. See defconfig file for an example configuration -and a list of available options and additional notes. - -The build time configuration can be used to select only the needed -features and limit the binary size and requirements for external -libraries. The main configuration parts are the selection of which -driver interfaces (e.g., hostap, madwifi, ..) and which authentication -methods (e.g., EAP-TLS, EAP-PEAP, ..) are included. - -Following build time configuration options are used to control IEEE -802.1X/EAPOL and EAP state machines and all EAP methods. Including -TLS, PEAP, or TTLS will require linking wpa_supplicant with OpenSSL -library for TLS implementation. Alternatively, GnuTLS or the internal -TLSv1 implementation can be used for TLS functionaly. - -CONFIG_IEEE8021X_EAPOL=y -CONFIG_EAP_MD5=y -CONFIG_EAP_MSCHAPV2=y -CONFIG_EAP_TLS=y -CONFIG_EAP_PEAP=y -CONFIG_EAP_TTLS=y -CONFIG_EAP_GTC=y -CONFIG_EAP_OTP=y -CONFIG_EAP_SIM=y -CONFIG_EAP_AKA=y -CONFIG_EAP_PSK=y -CONFIG_EAP_SAKE=y -CONFIG_EAP_GPSK=y -CONFIG_EAP_PAX=y -CONFIG_EAP_LEAP=y - -Following option can be used to include GSM SIM/USIM interface for GSM/UMTS -authentication algorithm (for EAP-SIM/EAP-AKA). This requires pcsc-lite -(http://www.linuxnet.com/) for smart card access. - -CONFIG_PCSC=y - -Following options can be added to .config to select which driver -interfaces are included. Hermes driver interface needs to be downloaded -from Agere (see above). CONFIG_WIRELESS_EXTENSION will be used -automatically if any of the selected drivers need it. - -CONFIG_WIRELESS_EXTENSION=y -CONFIG_DRIVER_HOSTAP=y -CONFIG_DRIVER_HERMES=y -CONFIG_DRIVER_MADWIFI=y -CONFIG_DRIVER_ATMEL=y -CONFIG_DRIVER_WEXT=y -CONFIG_DRIVER_NDISWRAPPER=y -CONFIG_DRIVER_BROADCOM=y -CONFIG_DRIVER_IPW=y -CONFIG_DRIVER_BSD=y -CONFIG_DRIVER_NDIS=y - -Following example includes all features and driver interfaces that are -included in the wpa_supplicant package: - -CONFIG_DRIVER_HOSTAP=y -CONFIG_DRIVER_HERMES=y -CONFIG_DRIVER_MADWIFI=y -CONFIG_DRIVER_ATMEL=y -CONFIG_DRIVER_WEXT=y -CONFIG_DRIVER_NDISWRAPPER=y -CONFIG_DRIVER_BROADCOM=y -CONFIG_DRIVER_IPW=y -CONFIG_DRIVER_BSD=y -CONFIG_DRIVER_NDIS=y -CONFIG_WIRELESS_EXTENSION=y -CONFIG_IEEE8021X_EAPOL=y -CONFIG_EAP_MD5=y -CONFIG_EAP_MSCHAPV2=y -CONFIG_EAP_TLS=y -CONFIG_EAP_PEAP=y -CONFIG_EAP_TTLS=y -CONFIG_EAP_GTC=y -CONFIG_EAP_OTP=y -CONFIG_EAP_SIM=y -CONFIG_EAP_AKA=y -CONFIG_EAP_PSK=y -CONFIG_EAP_SAKE=y -CONFIG_EAP_GPSK=y -CONFIG_EAP_PAX=y -CONFIG_EAP_LEAP=y -CONFIG_PCSC=y - -EAP-PEAP and EAP-TTLS will automatically include configured EAP -methods (MD5, OTP, GTC, MSCHAPV2) for inner authentication selection. - - -After you have created a configuration file, you can build -wpa_supplicant and wpa_cli with 'make' command. You may then install -the binaries to a suitable system directory, e.g., /usr/local/bin. - -Example commands: - -# build wpa_supplicant and wpa_cli -make -# install binaries (this may need root privileges) -cp wpa_cli wpa_supplicant /usr/local/bin - - -You will need to make a configuration file, e.g., -/etc/wpa_supplicant.conf, with network configuration for the networks -you are going to use. Configuration file section below includes -explanation fo the configuration file format and includes various -examples. Once the configuration is ready, you can test whether the -configuration work by first running wpa_supplicant with following -command to start it on foreground with debugging enabled: - -wpa_supplicant -iwlan0 -c/etc/wpa_supplicant.conf -d - -Assuming everything goes fine, you can start using following command -to start wpa_supplicant on background without debugging: - -wpa_supplicant -iwlan0 -c/etc/wpa_supplicant.conf -B - -Please note that if you included more than one driver interface in the -build time configuration (.config), you may need to specify which -interface to use by including -D<driver name> option on the command -line. See following section for more details on command line options -for wpa_supplicant. - - - -Command line options --------------------- - -usage: - wpa_supplicant [-BddfhKLqqtuvwW] [-P<pid file>] [-g<global ctrl>] \ - -i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] [-p<driver_param>] \ - [-b<br_ifname> [-N -i<ifname> -c<conf> [-C<ctrl>] [-D<driver>] \ - [-p<driver_param>] [-b<br_ifname>] ...] - -options: - -b = optional bridge interface name - -B = run daemon in the background - -c = Configuration file - -C = ctrl_interface parameter (only used if -c is not) - -i = interface name - -d = increase debugging verbosity (-dd even more) - -D = driver name - -f = Log output to default log location (normally /tmp) - -g = global ctrl_interface - -K = include keys (passwords, etc.) in debug output - -t = include timestamp in debug messages - -h = show this help text - -L = show license (GPL and BSD) - -p = driver parameters - -P = PID file - -q = decrease debugging verbosity (-qq even less) - -v = show version - -w = wait for interface to be added, if needed - -W = wait for a control interface monitor before starting - -N = start describing new interface - -drivers: - hostap = Host AP driver (Intersil Prism2/2.5/3) [default] - (this can also be used with Linuxant DriverLoader) - hermes = Agere Systems Inc. driver (Hermes-I/Hermes-II) - madwifi = MADWIFI 802.11 support (Atheros, etc.) - atmel = ATMEL AT76C5XXx (USB, PCMCIA) - wext = Linux wireless extensions (generic) - ndiswrapper = Linux ndiswrapper - broadcom = Broadcom wl.o driver - ipw = Intel ipw2100/2200 driver (old; use wext with Linux 2.6.13 or newer) - wired = wpa_supplicant wired Ethernet driver - bsd = BSD 802.11 support (Atheros, etc.) - ndis = Windows NDIS driver - -In most common cases, wpa_supplicant is started with - -wpa_supplicant -Bw -c/etc/wpa_supplicant.conf -iwlan0 - -This makes the process fork into background and wait for the wlan0 -interface if it is not available at startup time. - -The easiest way to debug problems, and to get debug log for bug -reports, is to start wpa_supplicant on foreground with debugging -enabled: - -wpa_supplicant -c/etc/wpa_supplicant.conf -iwlan0 -d - - -wpa_supplicant can control multiple interfaces (radios) either by -running one process for each interface separately or by running just -one process and list of options at command line. Each interface is -separated with -N argument. As an example, following command would -start wpa_supplicant for two interfaces: - -wpa_supplicant \ - -c wpa1.conf -i wlan0 -D hostap -N \ - -c wpa2.conf -i ath0 -D madwifi - - -If the interface is added in a Linux bridge (e.g., br0), the bridge -interface needs to be configured to wpa_supplicant in addition to the -main interface: - -wpa_supplicant -cw.conf -Dmadwifi -iath0 -bbr0 - - -Configuration file ------------------- - -wpa_supplicant is configured using a text file that lists all accepted -networks and security policies, including pre-shared keys. See -example configuration file, wpa_supplicant.conf, for detailed -information about the configuration format and supported fields. - -Changes to configuration file can be reloaded be sending SIGHUP signal -to wpa_supplicant ('killall -HUP wpa_supplicant'). Similarly, -reloading can be triggered with 'wpa_cli reconfigure' command. - -Configuration file can include one or more network blocks, e.g., one -for each used SSID. wpa_supplicant will automatically select the best -betwork based on the order of network blocks in the configuration -file, network security level (WPA/WPA2 is preferred), and signal -strength. - -Example configuration files for some common configurations: - -1) WPA-Personal (PSK) as home network and WPA-Enterprise with EAP-TLS as work - network - -# allow frontend (e.g., wpa_cli) to be used by all users in 'wheel' group -ctrl_interface=/var/run/wpa_supplicant -ctrl_interface_group=wheel -# -# home network; allow all valid ciphers -network={ - ssid="home" - scan_ssid=1 - key_mgmt=WPA-PSK - psk="very secret passphrase" -} -# -# work network; use EAP-TLS with WPA; allow only CCMP and TKIP ciphers -network={ - ssid="work" - scan_ssid=1 - key_mgmt=WPA-EAP - pairwise=CCMP TKIP - group=CCMP TKIP - eap=TLS - identity="user@example.com" - ca_cert="/etc/cert/ca.pem" - client_cert="/etc/cert/user.pem" - private_key="/etc/cert/user.prv" - private_key_passwd="password" -} - - -2) WPA-RADIUS/EAP-PEAP/MSCHAPv2 with RADIUS servers that use old peaplabel - (e.g., Funk Odyssey and SBR, Meetinghouse Aegis, Interlink RAD-Series) - -ctrl_interface=/var/run/wpa_supplicant -ctrl_interface_group=wheel -network={ - ssid="example" - scan_ssid=1 - key_mgmt=WPA-EAP - eap=PEAP - identity="user@example.com" - password="foobar" - ca_cert="/etc/cert/ca.pem" - phase1="peaplabel=0" - phase2="auth=MSCHAPV2" -} - - -3) EAP-TTLS/EAP-MD5-Challenge configuration with anonymous identity for the - unencrypted use. Real identity is sent only within an encrypted TLS tunnel. - -ctrl_interface=/var/run/wpa_supplicant -ctrl_interface_group=wheel -network={ - ssid="example" - scan_ssid=1 - key_mgmt=WPA-EAP - eap=TTLS - identity="user@example.com" - anonymous_identity="anonymous@example.com" - password="foobar" - ca_cert="/etc/cert/ca.pem" - phase2="auth=MD5" -} - - -4) IEEE 802.1X (i.e., no WPA) with dynamic WEP keys (require both unicast and - broadcast); use EAP-TLS for authentication - -ctrl_interface=/var/run/wpa_supplicant -ctrl_interface_group=wheel -network={ - ssid="1x-test" - scan_ssid=1 - key_mgmt=IEEE8021X - eap=TLS - identity="user@example.com" - ca_cert="/etc/cert/ca.pem" - client_cert="/etc/cert/user.pem" - private_key="/etc/cert/user.prv" - private_key_passwd="password" - eapol_flags=3 -} - - -5) Catch all example that allows more or less all configuration modes. The - configuration options are used based on what security policy is used in the - selected SSID. This is mostly for testing and is not recommended for normal - use. - -ctrl_interface=/var/run/wpa_supplicant -ctrl_interface_group=wheel -network={ - ssid="example" - scan_ssid=1 - key_mgmt=WPA-EAP WPA-PSK IEEE8021X NONE - pairwise=CCMP TKIP - group=CCMP TKIP WEP104 WEP40 - psk="very secret passphrase" - eap=TTLS PEAP TLS - identity="user@example.com" - password="foobar" - ca_cert="/etc/cert/ca.pem" - client_cert="/etc/cert/user.pem" - private_key="/etc/cert/user.prv" - private_key_passwd="password" - phase1="peaplabel=0" - ca_cert2="/etc/cert/ca2.pem" - client_cert2="/etc/cer/user.pem" - private_key2="/etc/cer/user.prv" - private_key2_passwd="password" -} - - -6) Authentication for wired Ethernet. This can be used with 'wired' interface - (-Dwired on command line). - -ctrl_interface=/var/run/wpa_supplicant -ctrl_interface_group=wheel -ap_scan=0 -network={ - key_mgmt=IEEE8021X - eap=MD5 - identity="user" - password="password" - eapol_flags=0 -} - - - -Certificates ------------- - -Some EAP authentication methods require use of certificates. EAP-TLS -uses both server side and client certificates whereas EAP-PEAP and -EAP-TTLS only require the server side certificate. When client -certificate is used, a matching private key file has to also be -included in configuration. If the private key uses a passphrase, this -has to be configured in wpa_supplicant.conf ("private_key_passwd"). - -wpa_supplicant supports X.509 certificates in PEM and DER -formats. User certificate and private key can be included in the same -file. - -If the user certificate and private key is received in PKCS#12/PFX -format, they need to be converted to suitable PEM/DER format for -wpa_supplicant. This can be done, e.g., with following commands: - -# convert client certificate and private key to PEM format -openssl pkcs12 -in example.pfx -out user.pem -clcerts -# convert CA certificate (if included in PFX file) to PEM format -openssl pkcs12 -in example.pfx -out ca.pem -cacerts -nokeys - - - -wpa_cli -------- - -wpa_cli is a text-based frontend program for interacting with -wpa_supplicant. It is used to query current status, change -configuration, trigger events, and request interactive user input. - -wpa_cli can show the current authentication status, selected security -mode, dot11 and dot1x MIBs, etc. In addition, it can configure some -variables like EAPOL state machine parameters and trigger events like -reassociation and IEEE 802.1X logoff/logon. wpa_cli provides a user -interface to request authentication information, like username and -password, if these are not included in the configuration. This can be -used to implement, e.g., one-time-passwords or generic token card -authentication where the authentication is based on a -challenge-response that uses an external device for generating the -response. - -The control interface of wpa_supplicant can be configured to allow -non-root user access (ctrl_interface_group in the configuration -file). This makes it possible to run wpa_cli with a normal user -account. - -wpa_cli supports two modes: interactive and command line. Both modes -share the same command set and the main difference is in interactive -mode providing access to unsolicited messages (event messages, -username/password requests). - -Interactive mode is started when wpa_cli is executed without including -the command as a command line parameter. Commands are then entered on -the wpa_cli prompt. In command line mode, the same commands are -entered as command line arguments for wpa_cli. - - -Interactive authentication parameters request - -When wpa_supplicant need authentication parameters, like username and -password, which are not present in the configuration file, it sends a -request message to all attached frontend programs, e.g., wpa_cli in -interactive mode. wpa_cli shows these requests with -"CTRL-REQ-<type>-<id>:<text>" prefix. <type> is IDENTITY, PASSWORD, or -OTP (one-time-password). <id> is a unique identifier for the current -network. <text> is description of the request. In case of OTP request, -it includes the challenge from the authentication server. - -The reply to these requests can be given with 'identity', 'password', -and 'otp' commands. <id> needs to be copied from the the matching -request. 'password' and 'otp' commands can be used regardless of -whether the request was for PASSWORD or OTP. The main difference -between these two commands is that values given with 'password' are -remembered as long as wpa_supplicant is running whereas values given -with 'otp' are used only once and then forgotten, i.e., wpa_supplicant -will ask frontend for a new value for every use. This can be used to -implement one-time-password lists and generic token card -based -authentication. - -Example request for password and a matching reply: - -CTRL-REQ-PASSWORD-1:Password needed for SSID foobar -> password 1 mysecretpassword - -Example request for generic token card challenge-response: - -CTRL-REQ-OTP-2:Challenge 1235663 needed for SSID foobar -> otp 2 9876 - - -wpa_cli commands - - status = get current WPA/EAPOL/EAP status - mib = get MIB variables (dot1x, dot11) - help = show this usage help - interface [ifname] = show interfaces/select interface - level <debug level> = change debug level - license = show full wpa_cli license - logoff = IEEE 802.1X EAPOL state machine logoff - logon = IEEE 802.1X EAPOL state machine logon - set = set variables (shows list of variables when run without arguments) - pmksa = show PMKSA cache - reassociate = force reassociation - reconfigure = force wpa_supplicant to re-read its configuration file - preauthenticate <BSSID> = force preauthentication - identity <network id> <identity> = configure identity for an SSID - password <network id> <password> = configure password for an SSID - pin <network id> <pin> = configure pin for an SSID - otp <network id> <password> = configure one-time-password for an SSID - passphrase <network id> <passphrase> = configure private key passphrase - for an SSID - bssid <network id> <BSSID> = set preferred BSSID for an SSID - list_networks = list configured networks - select_network <network id> = select a network (disable others) - enable_network <network id> = enable a network - disable_network <network id> = disable a network - add_network = add a network - remove_network <network id> = remove a network - set_network <network id> <variable> <value> = set network variables (shows - list of variables when run without arguments) - get_network <network id> <variable> = get network variables - save_config = save the current configuration - disconnect = disconnect and wait for reassociate command before connecting - scan = request new BSS scan - scan_results = get latest scan results - get_capability <eap/pairwise/group/key_mgmt/proto/auth_alg> = get capabilies - terminate = terminate wpa_supplicant - quit = exit wpa_cli - - -wpa_cli command line options - -wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] [-a<action file>] \ - [-P<pid file>] [-g<global ctrl>] [command..] - -h = help (show this usage text) - -v = shown version information - -a = run in daemon mode executing the action file based on events from - wpa_supplicant - -B = run a daemon in the background - default path: /var/run/wpa_supplicant - default interface: first interface found in socket path - - -Using wpa_cli to run external program on connect/disconnect ------------------------------------------------------------ - -wpa_cli can used to run external programs whenever wpa_supplicant -connects or disconnects from a network. This can be used, e.g., to -update network configuration and/or trigget DHCP client to update IP -addresses, etc. - -One wpa_cli process in "action" mode needs to be started for each -interface. For example, the following command starts wpa_cli for the -default ingterface (-i can be used to select the interface in case of -more than one interface being used at the same time): - -wpa_cli -a/sbin/wpa_action.sh -B - -The action file (-a option, /sbin/wpa_action.sh in this example) will -be executed whenever wpa_supplicant completes authentication (connect -event) or detects disconnection). The action script will be called -with two command line arguments: interface name and event (CONNECTED -or DISCONNECTED). If the action script needs to get more information -about the current network, it can use 'wpa_cli status' to query -wpa_supplicant for more information. - -Following example can be used as a simple template for an action -script: - -#!/bin/sh - -IFNAME=$1 -CMD=$2 - -if [ "$CMD" == "CONNECTED" ]; then - SSID=`wpa_cli -i$IFNAME status | grep ^ssid= | cut -f2- -d=` - # configure network, signal DHCP client, etc. -fi - -if [ "$CMD" == "DISCONNECTED" ]; then - # remove network configuration, if needed -fi - - - -Integrating with pcmcia-cs/cardmgr scripts ------------------------------------------- - -wpa_supplicant needs to be running when using a wireless network with -WPA. It can be started either from system startup scripts or from -pcmcia-cs/cardmgr scripts (when using PC Cards). WPA handshake must be -completed before data frames can be exchanged, so wpa_supplicant -should be started before DHCP client. - -Command line option '-w' can be used if wpa_supplicant is started -before the wireless LAN interface is present (e.g., before inserting -the PC Card) or is not yet up. - -For example, following small changes to pcmcia-cs scripts can be used -to enable WPA support: - -Add MODE="Managed" and WPA="y" to the network scheme in -/etc/pcmcia/wireless.opts. - -Add the following block to the end of 'start' action handler in -/etc/pcmcia/wireless: - - if [ "$WPA" = "y" -a -x /usr/local/bin/wpa_supplicant ]; then - /usr/local/bin/wpa_supplicant -Bw -c/etc/wpa_supplicant.conf \ - -i$DEVICE - fi - -Add the following block to the end of 'stop' action handler (may need -to be separated from other actions) in /etc/pcmcia/wireless: - - if [ "$WPA" = "y" -a -x /usr/local/bin/wpa_supplicant ]; then - killall wpa_supplicant - fi - -This will make cardmgr start wpa_supplicant when the card is plugged -in. wpa_supplicant will wait until the interface is set up--either -when a static IP address is configured or when DHCP client is -started--and will then negotiate keys with the AP. - - - -Dynamic interface add and operation without configuration files ---------------------------------------------------------------- - -wpa_supplicant can be started without any configuration files or -network interfaces. When used in this way, a global (i.e., per -wpa_supplicant process) control interface is used to add and remove -network interfaces. Each network interface can then be configured -through a per-network interface control interface. For example, -following commands show how to start wpa_supplicant without any -network interfaces and then add a network interface and configure a -network (SSID): - -# Start wpa_supplicant in the background -wpa_supplicant -g/var/run/wpa_supplicant-global -B - -# Add a new interface (wlan0, no configuration file, driver=wext, and -# enable control interface) -wpa_cli -g/var/run/wpa_supplicant-global interface_add wlan0 \ - "" wext /var/run/wpa_supplicant - -# Configure a network using the newly added network interface: -wpa_cli -iwlan0 add_network -wpa_cli -iwlan0 set_network 0 ssid '"test"' -wpa_cli -iwlan0 set_network 0 key_mgmt WPA-PSK -wpa_cli -iwlan0 set_network 0 psk '"12345678"' -wpa_cli -iwlan0 set_network 0 pairwise TKIP -wpa_cli -iwlan0 set_network 0 group TKIP -wpa_cli -iwlan0 set_network 0 proto WPA -wpa_cli -iwlan0 enable_network 0 - -# At this point, the new network interface should start trying to associate -# with the WPA-PSK network using SSID test. - -# Remove network interface -wpa_cli -g/var/run/wpa_supplicant-global interface_remove wlan0 diff --git a/contrib/wpa_supplicant/aes.c b/contrib/wpa_supplicant/aes.c deleted file mode 100644 index 1a2459b3e013..000000000000 --- a/contrib/wpa_supplicant/aes.c +++ /dev/null @@ -1,1107 +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 <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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" - -/* - * rijndael-alg-fst.c - * - * @version 3.0 (December 2000) - * - * Optimised ANSI C code for the Rijndael cipher (now AES) - * - * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be> - * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be> - * @author Paulo Barreto <paulo.barreto@terra.com.br> - * - * 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. - */ - -/* #define FULL_UNROLL */ -#define AES_SMALL_TABLES - - -/* -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]; -*/ - -static 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 -static 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, -}; -static 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, -}; -static 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, -}; -static 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 */ -static 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 -static 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, -}; -static 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, -}; -static 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, -}; -static 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, -}; -static 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 */ -static 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, -}; -static 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 */ - - -#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 */ - -#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) - -#ifdef _MSC_VER -#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 - -/** - * 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; - } -} - -/** - * 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 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 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); -} - - - -/* Generic wrapper functions for AES functions */ - -void * aes_encrypt_init(const u8 *key, size_t len) -{ - u32 *rk; - if (len != 16) - return NULL; - rk = os_malloc(4 * 44); - 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_free(ctx); -} - - -void * aes_decrypt_init(const u8 *key, size_t len) -{ - u32 *rk; - if (len != 16) - return NULL; - rk = os_malloc(4 * 44); - if (rk == NULL) - return NULL; - rijndaelKeySetupDec(rk, key); - return rk; -} - - -void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) -{ - rijndaelDecrypt(ctx, crypt, plain); -} - - -void aes_decrypt_deinit(void *ctx) -{ - os_free(ctx); -} diff --git a/contrib/wpa_supplicant/aes.h b/contrib/wpa_supplicant/aes.h deleted file mode 100644 index 6b9f4147afb1..000000000000 --- a/contrib/wpa_supplicant/aes.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * AES functions - * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 - -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/contrib/wpa_supplicant/aes_wrap.c b/contrib/wpa_supplicant/aes_wrap.c deleted file mode 100644 index 765b1ca871ad..000000000000 --- a/contrib/wpa_supplicant/aes_wrap.c +++ /dev/null @@ -1,515 +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 <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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_wrap.h" -#include "crypto.h" - -#ifdef INTERNAL_AES -#include "aes.c" -#endif /* INTERNAL_AES */ - - -#ifndef CONFIG_NO_AES_WRAP - -/** - * 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; -} - -#endif /* CONFIG_NO_AES_WRAP */ - - -/** - * 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; -} - - -#define BLOCK_SIZE 16 - -#ifndef CONFIG_NO_AES_OMAC1 - -static void gf_mulx(u8 *pad) -{ - int i, carry; - - carry = pad[0] & 0x80; - for (i = 0; i < BLOCK_SIZE - 1; i++) - pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7); - pad[BLOCK_SIZE - 1] <<= 1; - if (carry) - pad[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 - */ -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[BLOCK_SIZE], pad[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, 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 >= BLOCK_SIZE) { - for (i = 0; i < BLOCK_SIZE; i++) { - cbc[i] ^= *pos++; - if (pos >= end) { - e++; - pos = addr[e]; - end = pos + len[e]; - } - } - if (left > BLOCK_SIZE) - aes_encrypt(ctx, cbc, cbc); - left -= BLOCK_SIZE; - } - - os_memset(pad, 0, 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 < 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); -} - -#endif /* CONFIG_NO_AES_OMAC1 */ - - -/** - * 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; -} - - -#ifndef CONFIG_NO_AES_CTR - -/** - * 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[BLOCK_SIZE], buf[BLOCK_SIZE]; - - ctx = aes_encrypt_init(key, 16); - if (ctx == NULL) - return -1; - os_memcpy(counter, nonce, BLOCK_SIZE); - - while (left > 0) { - aes_encrypt(ctx, counter, buf); - - len = (left < BLOCK_SIZE) ? left : BLOCK_SIZE; - for (j = 0; j < len; j++) - pos[j] ^= buf[j]; - pos += len; - left -= len; - - for (i = BLOCK_SIZE - 1; i >= 0; i--) { - counter[i]++; - if (counter[i]) - break; - } - } - aes_encrypt_deinit(ctx); - return 0; -} - -#endif /* CONFIG_NO_AES_CTR */ - - -#ifndef CONFIG_NO_AES_EAX - -/** - * 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[BLOCK_SIZE], hdr_mac[BLOCK_SIZE], data_mac[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); - omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac); - - buf[15] = 1; - os_memcpy(buf + 16, hdr, hdr_len); - omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac); - - aes_128_ctr_encrypt(key, nonce_mac, data, data_len); - buf[15] = 2; - os_memcpy(buf + 16, data, data_len); - omac1_aes_128(key, buf, 16 + data_len, data_mac); - - os_free(buf); - - for (i = 0; i < BLOCK_SIZE; i++) - tag[i] = nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i]; - - return 0; -} - - -/** - * 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[BLOCK_SIZE], hdr_mac[BLOCK_SIZE], data_mac[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); - omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac); - - buf[15] = 1; - os_memcpy(buf + 16, hdr, hdr_len); - omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac); - - buf[15] = 2; - os_memcpy(buf + 16, data, data_len); - omac1_aes_128(key, buf, 16 + data_len, data_mac); - - os_free(buf); - - for (i = 0; i < BLOCK_SIZE; i++) { - if (tag[i] != (nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i])) - return -2; - } - - aes_128_ctr_encrypt(key, nonce_mac, data, data_len); - - return 0; -} - -#endif /* CONFIG_NO_AES_EAX */ - - -#ifndef CONFIG_NO_AES_CBC - -/** - * 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[BLOCK_SIZE]; - u8 *pos = data; - int i, j, blocks; - - ctx = aes_encrypt_init(key, 16); - if (ctx == NULL) - return -1; - os_memcpy(cbc, iv, BLOCK_SIZE); - - blocks = data_len / BLOCK_SIZE; - for (i = 0; i < blocks; i++) { - for (j = 0; j < BLOCK_SIZE; j++) - cbc[j] ^= pos[j]; - aes_encrypt(ctx, cbc, cbc); - os_memcpy(pos, cbc, BLOCK_SIZE); - pos += 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[BLOCK_SIZE], tmp[BLOCK_SIZE]; - u8 *pos = data; - int i, j, blocks; - - ctx = aes_decrypt_init(key, 16); - if (ctx == NULL) - return -1; - os_memcpy(cbc, iv, BLOCK_SIZE); - - blocks = data_len / BLOCK_SIZE; - for (i = 0; i < blocks; i++) { - os_memcpy(tmp, pos, BLOCK_SIZE); - aes_decrypt(ctx, pos, pos); - for (j = 0; j < BLOCK_SIZE; j++) - pos[j] ^= cbc[j]; - os_memcpy(cbc, tmp, BLOCK_SIZE); - pos += BLOCK_SIZE; - } - aes_decrypt_deinit(ctx); - return 0; -} - -#endif /* CONFIG_NO_AES_CBC */ diff --git a/contrib/wpa_supplicant/aes_wrap.h b/contrib/wpa_supplicant/aes_wrap.h deleted file mode 100644 index 5eb4342a5bf9..000000000000 --- a/contrib/wpa_supplicant/aes_wrap.h +++ /dev/null @@ -1,44 +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 <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher); -int aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain); -int omac1_aes_128_vector(const u8 *key, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac); -int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac); -int aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out); -int aes_128_ctr_encrypt(const u8 *key, const u8 *nonce, - u8 *data, size_t data_len); -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); -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); -int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, - size_t data_len); -int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, - size_t data_len); - -#endif /* AES_WRAP_H */ diff --git a/contrib/wpa_supplicant/asn1.c b/contrib/wpa_supplicant/asn1.c deleted file mode 100644 index 96bc1ac78a9d..000000000000 --- a/contrib/wpa_supplicant/asn1.c +++ /dev/null @@ -1,209 +0,0 @@ -/* - * ASN.1 DER parsing - * Copyright (c) 2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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_INTERNAL_X509 - -#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_get_oid(const u8 *buf, size_t len, struct asn1_oid *oid, - const u8 **next) -{ - struct asn1_hdr hdr; - const u8 *pos, *end; - unsigned long val; - u8 tmp; - - os_memset(oid, 0, sizeof(*oid)); - - 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; - } - - pos = hdr.payload; - end = hdr.payload + hdr.length; - *next = end; - - 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; -} - - -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; -} - -#endif /* CONFIG_INTERNAL_X509 */ diff --git a/contrib/wpa_supplicant/asn1.h b/contrib/wpa_supplicant/asn1.h deleted file mode 100644 index c02ada8278a2..000000000000 --- a/contrib/wpa_supplicant/asn1.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * ASN.1 DER parsing - * Copyright (c) 2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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_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/contrib/wpa_supplicant/asn1_test.c b/contrib/wpa_supplicant/asn1_test.c deleted file mode 100644 index a5c77535309f..000000000000 --- a/contrib/wpa_supplicant/asn1_test.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Testing tool for ASN.1/X.509v3 routines - * Copyright (c) 2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "x509v3.h" - -extern int wpa_debug_level; - - -static const char * asn1_class_str(int class) -{ - switch (class) { - case ASN1_CLASS_UNIVERSAL: - return "Universal"; - case ASN1_CLASS_APPLICATION: - return "Application"; - case ASN1_CLASS_CONTEXT_SPECIFIC: - return "Context-specific"; - case ASN1_CLASS_PRIVATE: - return "Private"; - default: - return "?"; - } -} - - -int asn1_parse(const u8 *buf, size_t len, int level) -{ - const u8 *pos, *prev, *end; - char prefix[10], str[100]; - int _level; - struct asn1_hdr hdr; - struct asn1_oid oid; - u8 tmp; - - _level = level; - if ((size_t) _level > sizeof(prefix) - 1) - _level = sizeof(prefix) - 1; - memset(prefix, ' ', _level); - prefix[_level] = '\0'; - - pos = buf; - end = buf + len; - - while (pos < end) { - if (asn1_get_next(pos, end - pos, &hdr) < 0) - return -1; - - prev = pos; - pos = hdr.payload; - - wpa_printf(MSG_MSGDUMP, "ASN.1:%s Class %d(%s) P/C %d(%s) " - "Tag %u Length %u", - prefix, hdr.class, asn1_class_str(hdr.class), - hdr.constructed, - hdr.constructed ? "Constructed" : "Primitive", - hdr.tag, hdr.length); - - if (hdr.class == ASN1_CLASS_CONTEXT_SPECIFIC && - hdr.constructed) { - if (asn1_parse(pos, hdr.length, level + 1) < 0) - return -1; - pos += hdr.length; - } - - if (hdr.class != ASN1_CLASS_UNIVERSAL) - continue; - - switch (hdr.tag) { - case ASN1_TAG_EOC: - if (hdr.length) { - wpa_printf(MSG_DEBUG, "ASN.1: Non-zero " - "end-of-contents length (%u)", - hdr.length); - return -1; - } - wpa_printf(MSG_MSGDUMP, "ASN.1:%s EOC", prefix); - break; - case ASN1_TAG_BOOLEAN: - if (hdr.length != 1) { - wpa_printf(MSG_DEBUG, "ASN.1: Unexpected " - "Boolean length (%u)", hdr.length); - return -1; - } - tmp = *pos++; - wpa_printf(MSG_MSGDUMP, "ASN.1:%s Boolean %s", - prefix, tmp ? "TRUE" : "FALSE"); - break; - case ASN1_TAG_INTEGER: - wpa_hexdump(MSG_MSGDUMP, "ASN.1: INTEGER", - pos, hdr.length); - pos += hdr.length; - break; - case ASN1_TAG_BITSTRING: - wpa_hexdump(MSG_MSGDUMP, "ASN.1: BitString", - pos, hdr.length); - pos += hdr.length; - break; - case ASN1_TAG_OCTETSTRING: - wpa_hexdump(MSG_MSGDUMP, "ASN.1: OctetString", - pos, hdr.length); - pos += hdr.length; - break; - case ASN1_TAG_NULL: - if (hdr.length) { - wpa_printf(MSG_DEBUG, "ASN.1: Non-zero Null " - "length (%u)", hdr.length); - return -1; - } - wpa_printf(MSG_MSGDUMP, "ASN.1:%s Null", prefix); - break; - case ASN1_TAG_OID: - if (asn1_get_oid(prev, end - prev, &oid, &prev) < 0) { - wpa_printf(MSG_DEBUG, "ASN.1: Invalid OID"); - return -1; - } - asn1_oid_to_str(&oid, str, sizeof(str)); - wpa_printf(MSG_DEBUG, "ASN.1:%s OID %s", prefix, str); - pos += hdr.length; - break; - case ANS1_TAG_RELATIVE_OID: - wpa_hexdump(MSG_MSGDUMP, "ASN.1: Relative OID", - pos, hdr.length); - pos += hdr.length; - break; - case ASN1_TAG_SEQUENCE: - wpa_printf(MSG_MSGDUMP, "ASN.1:%s SEQUENCE", prefix); - if (asn1_parse(pos, hdr.length, level + 1) < 0) - return -1; - pos += hdr.length; - break; - case ASN1_TAG_SET: - wpa_printf(MSG_MSGDUMP, "ASN.1:%s SET", prefix); - if (asn1_parse(pos, hdr.length, level + 1) < 0) - return -1; - pos += hdr.length; - break; - case ASN1_TAG_PRINTABLESTRING: - wpa_hexdump_ascii(MSG_MSGDUMP, - "ASN.1: PrintableString", - pos, hdr.length); - pos += hdr.length; - break; - case ASN1_TAG_IA5STRING: - wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: IA5String", - pos, hdr.length); - pos += hdr.length; - break; - case ASN1_TAG_UTCTIME: - wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: UTCTIME", - pos, hdr.length); - pos += hdr.length; - break; - case ASN1_TAG_VISIBLESTRING: - wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: VisibleString", - pos, hdr.length); - pos += hdr.length; - break; - default: - wpa_printf(MSG_DEBUG, "ASN.1: Unknown tag %d", - hdr.tag); - return -1; - } - } - - return 0; -} - - -int main(int argc, char *argv[]) -{ - FILE *f; - u8 buf[3000]; - size_t len; - struct x509_certificate *cert; - - wpa_debug_level = 0; - - f = fopen(argv[1], "rb"); - if (f == NULL) - return -1; - len = fread(buf, 1, sizeof(buf), f); - fclose(f); - - if (asn1_parse(buf, len, 0) < 0) - printf("Failed to parse DER ASN.1\n"); - - printf("\n\n"); - - cert = x509_certificate_parse(buf, len); - if (cert == NULL) - printf("Failed to parse X.509 certificate\n"); - x509_certificate_free(cert); - - return 0; -} diff --git a/contrib/wpa_supplicant/base64.c b/contrib/wpa_supplicant/base64.c deleted file mode 100644 index 8b1da25dbde6..000000000000 --- a/contrib/wpa_supplicant/base64.c +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Base64 encoding/decoding (RFC1341) - * Copyright (c) 2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 */ - 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; -} - - -#ifdef TEST_MAIN -#include <stdio.h> - -int main(int argc, char *argv[]) -{ - FILE *f; - size_t len, elen; - unsigned char *buf, *e; - - if (argc != 4) { - printf("Usage: base64 <encode|decode> <in file> <out file>\n"); - return -1; - } - - buf = os_readfile(argv[2], &len); - if (buf == NULL) - return -1; - - if (strcmp(argv[1], "encode") == 0) - e = base64_encode(buf, len, &elen); - else - e = base64_decode(buf, len, &elen); - if (e == NULL) - return -2; - f = fopen(argv[3], "w"); - if (f == NULL) - return -3; - fwrite(e, 1, elen, f); - fclose(f); - free(e); - - return 0; -} -#endif /* TEST_MAIN */ diff --git a/contrib/wpa_supplicant/base64.h b/contrib/wpa_supplicant/base64.h deleted file mode 100644 index 73312dde8f64..000000000000 --- a/contrib/wpa_supplicant/base64.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Base64 encoding/decoding (RFC1341) - * Copyright (c) 2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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/contrib/wpa_supplicant/bignum.c b/contrib/wpa_supplicant/bignum.c deleted file mode 100644 index 4c304c2a5af5..000000000000 --- a/contrib/wpa_supplicant/bignum.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Big number math - * Copyright (c) 2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 <tommath.h> -#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 - * @a: 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/contrib/wpa_supplicant/bignum.h b/contrib/wpa_supplicant/bignum.h deleted file mode 100644 index f25e26783a0a..000000000000 --- a/contrib/wpa_supplicant/bignum.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Big number math - * Copyright (c) 2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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/contrib/wpa_supplicant/build_config.h b/contrib/wpa_supplicant/build_config.h deleted file mode 100644 index 58bcda825345..000000000000 --- a/contrib/wpa_supplicant/build_config.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * wpa_supplicant/hostapd - Build time configuration defines - * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 EAP_TLS_FUNCS -#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 _CRT_SECURE_NO_DEPRECATE -#endif /* CONFIG_WIN32_DEFAULTS */ - -#endif /* BUILD_CONFIG_H */ diff --git a/contrib/wpa_supplicant/common.c b/contrib/wpa_supplicant/common.c deleted file mode 100644 index d0233d88f5d1..000000000000 --- a/contrib/wpa_supplicant/common.c +++ /dev/null @@ -1,646 +0,0 @@ -/* - * wpa_supplicant/hostapd / common helper functions, etc. - * Copyright (c) 2002-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 <syslog.h> -#endif /* CONFIG_DEBUG_SYSLOG */ - - -#ifdef CONFIG_DEBUG_FILE -static FILE *out_file = NULL; -#endif /* CONFIG_DEBUG_FILE */ -int wpa_debug_level = MSG_INFO; -int wpa_debug_show_keys = 0; -int wpa_debug_timestamp = 0; -int wpa_debug_syslog = 0; - - -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; -} - - -static 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 - * @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; -} - - -/** - * 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; - - /* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */ - os_get_time(&now); - sec = host_to_be32(now.sec + 2208988800U); /* Epoch to 1900 */ - /* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */ - usec = now.usec; - usec = host_to_be32(4295 * usec - (usec >> 5) - (usec >> 9)); - os_memcpy(buf, (u8 *) &sec, 4); - os_memcpy(buf + 4, (u8 *) &usec, 4); -} - - - -#ifndef CONFIG_NO_STDOUT_DEBUG - -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); -} - -void wpa_debug_open_syslog(void) -{ -#ifdef CONFIG_DEBUG_SYSLOG - openlog("wpa_supplicant", LOG_PID | LOG_NDELAY, LOG_DAEMON); - wpa_debug_syslog++; -#endif -} - -void wpa_debug_close_syslog(void) -{ -#ifdef CONFIG_DEBUG_SYSLOG - if (wpa_debug_syslog) - closelog(); -#endif -} - -#ifdef CONFIG_DEBUG_SYSLOG -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, 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); -} - - -int wpa_debug_open_file(const char *path) -{ -#ifdef CONFIG_DEBUG_FILE - if (!path) - return 0; - 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; -#endif /* CONFIG_DEBUG_FILE */ -} - -#endif /* CONFIG_NO_STDOUT_DEBUG */ - - -#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; -} - - -void wpa_msg(void *ctx, int level, char *fmt, ...) -{ - va_list ap; - char *buf; - const int buflen = 2048; - int len; - - buf = os_malloc(buflen); - if (buf == NULL) { - wpa_printf(MSG_ERROR, "wpa_msg: Failed to allocate message " - "buffer"); - return; - } - va_start(ap, fmt); - len = vsnprintf(buf, buflen, fmt, ap); - va_end(ap); - wpa_printf(level, "%s", buf); - if (wpa_msg_cb) - wpa_msg_cb(ctx, level, buf, len); - os_free(buf); -} -#endif /* CONFIG_NO_WPA_MSG */ - - -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(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; -} diff --git a/contrib/wpa_supplicant/common.h b/contrib/wpa_supplicant/common.h deleted file mode 100644 index a1d952b14589..000000000000 --- a/contrib/wpa_supplicant/common.h +++ /dev/null @@ -1,494 +0,0 @@ -/* - * wpa_supplicant/hostapd / common helper functions, etc. - * Copyright (c) 2002-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * $FreeBSD$ - */ - -#ifndef COMMON_H -#define COMMON_H - -#include "os.h" - -#ifdef __linux__ -#include <endian.h> -#include <byteswap.h> -#endif /* __linux__ */ - -#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) -#include <sys/types.h> -#include <sys/endian.h> -#define __BYTE_ORDER _BYTE_ORDER -#define __LITTLE_ENDIAN _LITTLE_ENDIAN -#define __BIG_ENDIAN _BIG_ENDIAN -#define bswap_16 bswap16 -#define bswap_32 bswap32 -#define bswap_64 bswap64 -#endif /* defined(__FreeBSD__) || defined(__NetBSD__) || - * defined(__DragonFly__) */ - -#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 CONFIG_NATIVE_WINDOWS -#include <winsock.h> - -typedef int socklen_t; - -#ifndef MSG_DONTWAIT -#define MSG_DONTWAIT 0 /* not supported */ -#endif - -#endif /* CONFIG_NATIVE_WINDOWS */ - -#if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS) - -#ifdef _MSC_VER -#define inline __inline -#endif /* _MSC_VER */ - -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) - -#else /* __CYGWIN__ */ - -#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) (n) -#define host_to_le16(n) (n) -#define be_to_host16(n) bswap_16(n) -#define host_to_be16(n) bswap_16(n) -#define le_to_host32(n) (n) -#define be_to_host32(n) bswap_32(n) -#define host_to_be32(n) bswap_32(n) -#define le_to_host64(n) (n) -#define host_to_le64(n) (n) -#define be_to_host64(n) bswap_64(n) -#define host_to_be64(n) 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 - -#endif /* __CYGWIN__ */ - -/* Macros for handling unaligned 16-bit variables */ -#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); \ - (a)[1] = (u8) (((u32) (val)) >> 8); \ - (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); \ - (a)[1] = (u8) (((u32) (val)) >> 16); \ - (a)[2] = (u8) (((u32) (val)) >> 8); \ - (a)[3] = (u8) (((u32) (val)) & 0xff); \ - } while (0) - -#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) - - -#ifndef ETH_ALEN -#define ETH_ALEN 6 -#endif - -#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 */ - -#ifndef WPA_TYPES_DEFINED -#ifdef CONFIG_USE_INTTYPES_H -#include <inttypes.h> -#else -#include <stdint.h> -#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 hostapd_get_rand os_get_random -int hwaddr_aton(const char *txt, u8 *addr); -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); - - -#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 - - -/* Debugging function - conditional printf and hex dump. Driver wrappers can - * use these for debugging purposes. */ - -enum { MSG_MSGDUMP, MSG_DEBUG, MSG_INFO, MSG_WARNING, MSG_ERROR }; - -#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_key(l,t,b,le) 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) - -#else /* CONFIG_NO_STDOUT_DEBUG */ - -int wpa_debug_open_file(const char *path); -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, 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); - -/** - * 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); - -/** - * 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); - -#endif /* CONFIG_NO_STDOUT_DEBUG */ - - -#ifdef CONFIG_NO_WPA_MSG -#define wpa_msg(args...) do { } while (0) -#define wpa_msg_register_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, 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); -#endif /* CONFIG_NO_WPA_MSG */ - - -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 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 - - -#ifdef _MSC_VER -#undef vsnprintf -#define vsnprintf _vsnprintf -#undef close -#define close closesocket -#endif /* _MSC_VER */ - - -#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 */ - -#define wpa_zalloc(s) os_zalloc((s)) - -#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(u8 *ssid, size_t ssid_len); - -typedef u32 __be32; -typedef u64 __be64; - -#endif /* COMMON_H */ diff --git a/contrib/wpa_supplicant/config.c b/contrib/wpa_supplicant/config.c deleted file mode 100644 index 6ea66de34eec..000000000000 --- a/contrib/wpa_supplicant/config.c +++ /dev/null @@ -1,1759 +0,0 @@ -/* - * WPA Supplicant / Configuration parser and common functions - * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "sha1.h" -#include "eapol_sm.h" -#include "eap.h" -#include "l2_packet.h" -#include "config.h" - - -/* - * Structure for network configuration parsing. This data is used to implement - * a generic parser for each network block variable. The table of configuration - * variables is defined below in this file (ssid_fields[]). - */ -struct parse_data { - /* Configuration variable name */ - char *name; - - /* Parser function for this variable */ - int (*parser)(const struct parse_data *data, struct wpa_ssid *ssid, - int line, const char *value); - - /* Writer function (i.e., to get the variable in text format from - * internal presentation). */ - char * (*writer)(const struct parse_data *data, struct wpa_ssid *ssid); - - /* Variable specific parameters for the parser. */ - void *param1, *param2, *param3, *param4; - - /* 0 = this variable can be included in debug output and ctrl_iface - * 1 = this variable contains key/private data and it must not be - * included in debug output unless explicitly requested. In - * addition, this variable will not be readable through the - * ctrl_iface. - */ - int key_data; -}; - - -static char * wpa_config_parse_string(const char *value, size_t *len) -{ - if (*value == '"') { - char *pos; - value++; - pos = os_strrchr(value, '"'); - if (pos == NULL || pos[1] != '\0') - return NULL; - *pos = '\0'; - *len = os_strlen(value); - return os_strdup(value); - } else { - u8 *str; - size_t tlen, hlen = os_strlen(value); - if (hlen & 1) - return NULL; - tlen = hlen / 2; - str = os_malloc(tlen + 1); - if (str == NULL) - return NULL; - if (hexstr2bin(value, str, tlen)) { - os_free(str); - return NULL; - } - str[tlen] = '\0'; - *len = tlen; - return (char *) str; - } -} - - -static int wpa_config_parse_str(const struct parse_data *data, - struct wpa_ssid *ssid, - int line, const char *value) -{ - size_t res_len, *dst_len; - char **dst, *tmp; - - tmp = wpa_config_parse_string(value, &res_len); - if (tmp == NULL) { - wpa_printf(MSG_ERROR, "Line %d: failed to parse %s '%s'.", - line, data->name, - data->key_data ? "[KEY DATA REMOVED]" : value); - return -1; - } - - if (data->key_data) { - wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name, - (u8 *) tmp, res_len); - } else { - wpa_hexdump_ascii(MSG_MSGDUMP, data->name, - (u8 *) tmp, res_len); - } - - if (data->param3 && res_len < (size_t) data->param3) { - wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu " - "min_len=%ld)", line, data->name, - (unsigned long) res_len, (long) data->param3); - os_free(tmp); - return -1; - } - - if (data->param4 && res_len > (size_t) data->param4) { - wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu " - "max_len=%ld)", line, data->name, - (unsigned long) res_len, (long) data->param4); - os_free(tmp); - return -1; - } - - dst = (char **) (((u8 *) ssid) + (long) data->param1); - dst_len = (size_t *) (((u8 *) ssid) + (long) data->param2); - os_free(*dst); - *dst = tmp; - if (data->param2) - *dst_len = res_len; - - return 0; -} - - -static int is_hex(const u8 *data, size_t len) -{ - size_t i; - - for (i = 0; i < len; i++) { - if (data[i] < 32 || data[i] >= 127) - return 1; - } - return 0; -} - - -static char * wpa_config_write_string_ascii(const u8 *value, size_t len) -{ - char *buf; - - buf = os_malloc(len + 3); - if (buf == NULL) - return NULL; - buf[0] = '"'; - os_memcpy(buf + 1, value, len); - buf[len + 1] = '"'; - buf[len + 2] = '\0'; - - return buf; -} - - -static char * wpa_config_write_string_hex(const u8 *value, size_t len) -{ - char *buf; - - buf = os_zalloc(2 * len + 1); - if (buf == NULL) - return NULL; - wpa_snprintf_hex(buf, 2 * len + 1, value, len); - - return buf; -} - - -static char * wpa_config_write_string(const u8 *value, size_t len) -{ - if (value == NULL) - return NULL; - - if (is_hex(value, len)) - return wpa_config_write_string_hex(value, len); - else - return wpa_config_write_string_ascii(value, len); -} - - -static char * wpa_config_write_str(const struct parse_data *data, - struct wpa_ssid *ssid) -{ - size_t len; - char **src; - - src = (char **) (((u8 *) ssid) + (long) data->param1); - if (*src == NULL) - return NULL; - - if (data->param2) - len = *((size_t *) (((u8 *) ssid) + (long) data->param2)); - else - len = os_strlen(*src); - - return wpa_config_write_string((const u8 *) *src, len); -} - - -static int wpa_config_parse_int(const struct parse_data *data, - struct wpa_ssid *ssid, - int line, const char *value) -{ - int *dst; - - dst = (int *) (((u8 *) ssid) + (long) data->param1); - *dst = atoi(value); - wpa_printf(MSG_MSGDUMP, "%s=%d (0x%x)", data->name, *dst, *dst); - - if (data->param3 && *dst < (long) data->param3) { - wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d " - "min_value=%ld)", line, data->name, *dst, - (long) data->param3); - *dst = (long) data->param3; - return -1; - } - - if (data->param4 && *dst > (long) data->param4) { - wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d " - "max_value=%ld)", line, data->name, *dst, - (long) data->param4); - *dst = (long) data->param4; - return -1; - } - - return 0; -} - - -static char * wpa_config_write_int(const struct parse_data *data, - struct wpa_ssid *ssid) -{ - int *src; - char *value; - - src = (int *) (((u8 *) ssid) + (long) data->param1); - - value = os_malloc(20); - if (value == NULL) - return NULL; - os_snprintf(value, 20, "%d", *src); - value[20 - 1] = '\0'; - return value; -} - - -static int wpa_config_parse_bssid(const struct parse_data *data, - struct wpa_ssid *ssid, int line, - const char *value) -{ - if (hwaddr_aton(value, ssid->bssid)) { - wpa_printf(MSG_ERROR, "Line %d: Invalid BSSID '%s'.", - line, value); - return -1; - } - ssid->bssid_set = 1; - wpa_hexdump(MSG_MSGDUMP, "BSSID", ssid->bssid, ETH_ALEN); - return 0; -} - - -static char * wpa_config_write_bssid(const struct parse_data *data, - struct wpa_ssid *ssid) -{ - char *value; - - if (!ssid->bssid_set) - return NULL; - - value = os_malloc(20); - if (value == NULL) - return NULL; - os_snprintf(value, 20, MACSTR, MAC2STR(ssid->bssid)); - value[20 - 1] = '\0'; - return value; -} - - -static int wpa_config_parse_psk(const struct parse_data *data, - struct wpa_ssid *ssid, int line, - const char *value) -{ - if (*value == '"') { - const char *pos; - size_t len; - - value++; - pos = os_strrchr(value, '"'); - if (pos) - len = pos - value; - else - len = os_strlen(value); - if (len < 8 || len > 63) { - wpa_printf(MSG_ERROR, "Line %d: Invalid passphrase " - "length %lu (expected: 8..63) '%s'.", - line, (unsigned long) len, value); - return -1; - } - wpa_hexdump_ascii_key(MSG_MSGDUMP, "PSK (ASCII passphrase)", - (u8 *) value, len); - if (ssid->passphrase && os_strlen(ssid->passphrase) == len && - os_memcmp(ssid->passphrase, value, len) == 0) - return 0; - ssid->psk_set = 0; - os_free(ssid->passphrase); - ssid->passphrase = os_malloc(len + 1); - if (ssid->passphrase == NULL) - return -1; - os_memcpy(ssid->passphrase, value, len); - ssid->passphrase[len] = '\0'; - return 0; - } - - if (hexstr2bin(value, ssid->psk, PMK_LEN) || - value[PMK_LEN * 2] != '\0') { - wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.", - line, value); - return -1; - } - - os_free(ssid->passphrase); - ssid->passphrase = NULL; - - ssid->psk_set = 1; - wpa_hexdump_key(MSG_MSGDUMP, "PSK", ssid->psk, PMK_LEN); - return 0; -} - - -static char * wpa_config_write_psk(const struct parse_data *data, - struct wpa_ssid *ssid) -{ - if (ssid->passphrase) - return wpa_config_write_string_ascii( - (const u8 *) ssid->passphrase, - os_strlen(ssid->passphrase)); - - if (ssid->psk_set) - return wpa_config_write_string_hex(ssid->psk, PMK_LEN); - - return NULL; -} - - -static int wpa_config_parse_proto(const struct parse_data *data, - struct wpa_ssid *ssid, int line, - const char *value) -{ - int val = 0, last, errors = 0; - 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") == 0) - val |= WPA_PROTO_WPA; - else if (os_strcmp(start, "RSN") == 0 || - os_strcmp(start, "WPA2") == 0) - val |= WPA_PROTO_RSN; - else { - wpa_printf(MSG_ERROR, "Line %d: invalid proto '%s'", - line, start); - errors++; - } - - if (last) - break; - start = end + 1; - } - os_free(buf); - - if (val == 0) { - wpa_printf(MSG_ERROR, - "Line %d: no proto values configured.", line); - errors++; - } - - wpa_printf(MSG_MSGDUMP, "proto: 0x%x", val); - ssid->proto = val; - return errors ? -1 : 0; -} - - -static char * wpa_config_write_proto(const struct parse_data *data, - struct wpa_ssid *ssid) -{ - int first = 1, ret; - char *buf, *pos, *end; - - pos = buf = os_zalloc(10); - if (buf == NULL) - return NULL; - end = buf + 10; - - if (ssid->proto & WPA_PROTO_WPA) { - ret = os_snprintf(pos, end - pos, "%sWPA", first ? "" : " "); - if (ret < 0 || ret >= end - pos) - return buf; - pos += ret; - first = 0; - } - - if (ssid->proto & WPA_PROTO_RSN) { - ret = os_snprintf(pos, end - pos, "%sRSN", first ? "" : " "); - if (ret < 0 || ret >= end - pos) - return buf; - pos += ret; - first = 0; - } - - return buf; -} - - -static int wpa_config_parse_key_mgmt(const struct parse_data *data, - struct wpa_ssid *ssid, int line, - const char *value) -{ - int val = 0, last, errors = 0; - 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; - else if (os_strcmp(start, "IEEE8021X") == 0) - val |= WPA_KEY_MGMT_IEEE8021X_NO_WPA; - else if (os_strcmp(start, "NONE") == 0) - val |= WPA_KEY_MGMT_NONE; - else if (os_strcmp(start, "WPA-NONE") == 0) - val |= WPA_KEY_MGMT_WPA_NONE; - else { - wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'", - line, start); - errors++; - } - - if (last) - break; - start = end + 1; - } - os_free(buf); - - if (val == 0) { - wpa_printf(MSG_ERROR, - "Line %d: no key_mgmt values configured.", line); - errors++; - } - - wpa_printf(MSG_MSGDUMP, "key_mgmt: 0x%x", val); - ssid->key_mgmt = val; - return errors ? -1 : 0; -} - - -static char * wpa_config_write_key_mgmt(const struct parse_data *data, - struct wpa_ssid *ssid) -{ - char *buf, *pos, *end; - int ret; - - pos = buf = os_zalloc(50); - if (buf == NULL) - return NULL; - end = buf + 50; - - if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) { - ret = os_snprintf(pos, end - pos, "%sWPA-PSK", - pos == buf ? "" : " "); - if (ret < 0 || ret >= end - pos) { - end[-1] = '\0'; - return buf; - } - pos += ret; - } - - if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X) { - ret = os_snprintf(pos, end - pos, "%sWPA-EAP", - pos == buf ? "" : " "); - if (ret < 0 || ret >= end - pos) { - end[-1] = '\0'; - return buf; - } - pos += ret; - } - - if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) { - ret = os_snprintf(pos, end - pos, "%sIEEE8021X", - pos == buf ? "" : " "); - if (ret < 0 || ret >= end - pos) { - end[-1] = '\0'; - return buf; - } - pos += ret; - } - - if (ssid->key_mgmt & WPA_KEY_MGMT_NONE) { - ret = os_snprintf(pos, end - pos, "%sNONE", - pos == buf ? "" : " "); - if (ret < 0 || ret >= end - pos) { - end[-1] = '\0'; - return buf; - } - pos += ret; - } - - if (ssid->key_mgmt & WPA_KEY_MGMT_WPA_NONE) { - ret = os_snprintf(pos, end - pos, "%sWPA-NONE", - pos == buf ? "" : " "); - if (ret < 0 || ret >= end - pos) { - end[-1] = '\0'; - return buf; - } - pos += ret; - } - - return buf; -} - - -static int wpa_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 char * wpa_config_write_cipher(int cipher) -{ - char *buf, *pos, *end; - int ret; - - pos = buf = os_zalloc(50); - if (buf == NULL) - return NULL; - end = buf + 50; - - if (cipher & WPA_CIPHER_CCMP) { - ret = os_snprintf(pos, end - pos, "%sCCMP", - pos == buf ? "" : " "); - if (ret < 0 || ret >= end - pos) { - end[-1] = '\0'; - return buf; - } - pos += ret; - } - - if (cipher & WPA_CIPHER_TKIP) { - ret = os_snprintf(pos, end - pos, "%sTKIP", - pos == buf ? "" : " "); - if (ret < 0 || ret >= end - pos) { - end[-1] = '\0'; - return buf; - } - pos += ret; - } - - if (cipher & WPA_CIPHER_WEP104) { - ret = os_snprintf(pos, end - pos, "%sWEP104", - pos == buf ? "" : " "); - if (ret < 0 || ret >= end - pos) { - end[-1] = '\0'; - return buf; - } - pos += ret; - } - - if (cipher & WPA_CIPHER_WEP40) { - ret = os_snprintf(pos, end - pos, "%sWEP40", - pos == buf ? "" : " "); - if (ret < 0 || ret >= end - pos) { - end[-1] = '\0'; - return buf; - } - pos += ret; - } - - if (cipher & WPA_CIPHER_NONE) { - ret = os_snprintf(pos, end - pos, "%sNONE", - pos == buf ? "" : " "); - if (ret < 0 || ret >= end - pos) { - end[-1] = '\0'; - return buf; - } - pos += ret; - } - - return buf; -} - - -static int wpa_config_parse_pairwise(const struct parse_data *data, - struct wpa_ssid *ssid, int line, - const char *value) -{ - int val; - val = wpa_config_parse_cipher(line, value); - if (val == -1) - return -1; - if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | WPA_CIPHER_NONE)) { - wpa_printf(MSG_ERROR, "Line %d: not allowed pairwise cipher " - "(0x%x).", line, val); - return -1; - } - - wpa_printf(MSG_MSGDUMP, "pairwise: 0x%x", val); - ssid->pairwise_cipher = val; - return 0; -} - - -static char * wpa_config_write_pairwise(const struct parse_data *data, - struct wpa_ssid *ssid) -{ - return wpa_config_write_cipher(ssid->pairwise_cipher); -} - - -static int wpa_config_parse_group(const struct parse_data *data, - struct wpa_ssid *ssid, int line, - const char *value) -{ - int val; - val = wpa_config_parse_cipher(line, value); - if (val == -1) - return -1; - if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | WPA_CIPHER_WEP104 | - WPA_CIPHER_WEP40)) { - wpa_printf(MSG_ERROR, "Line %d: not allowed group cipher " - "(0x%x).", line, val); - return -1; - } - - wpa_printf(MSG_MSGDUMP, "group: 0x%x", val); - ssid->group_cipher = val; - return 0; -} - - -static char * wpa_config_write_group(const struct parse_data *data, - struct wpa_ssid *ssid) -{ - return wpa_config_write_cipher(ssid->group_cipher); -} - - -static int wpa_config_parse_auth_alg(const struct parse_data *data, - struct wpa_ssid *ssid, int line, - const char *value) -{ - int val = 0, last, errors = 0; - 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, "OPEN") == 0) - val |= WPA_AUTH_ALG_OPEN; - else if (os_strcmp(start, "SHARED") == 0) - val |= WPA_AUTH_ALG_SHARED; - else if (os_strcmp(start, "LEAP") == 0) - val |= WPA_AUTH_ALG_LEAP; - else { - wpa_printf(MSG_ERROR, "Line %d: invalid auth_alg '%s'", - line, start); - errors++; - } - - if (last) - break; - start = end + 1; - } - os_free(buf); - - if (val == 0) { - wpa_printf(MSG_ERROR, - "Line %d: no auth_alg values configured.", line); - errors++; - } - - wpa_printf(MSG_MSGDUMP, "auth_alg: 0x%x", val); - ssid->auth_alg = val; - return errors ? -1 : 0; -} - - -static char * wpa_config_write_auth_alg(const struct parse_data *data, - struct wpa_ssid *ssid) -{ - char *buf, *pos, *end; - int ret; - - pos = buf = os_zalloc(30); - if (buf == NULL) - return NULL; - end = buf + 30; - - if (ssid->auth_alg & WPA_AUTH_ALG_OPEN) { - ret = os_snprintf(pos, end - pos, "%sOPEN", - pos == buf ? "" : " "); - if (ret < 0 || ret >= end - pos) { - end[-1] = '\0'; - return buf; - } - pos += ret; - } - - if (ssid->auth_alg & WPA_AUTH_ALG_SHARED) { - ret = os_snprintf(pos, end - pos, "%sSHARED", - pos == buf ? "" : " "); - if (ret < 0 || ret >= end - pos) { - end[-1] = '\0'; - return buf; - } - pos += ret; - } - - if (ssid->auth_alg & WPA_AUTH_ALG_LEAP) { - ret = os_snprintf(pos, end - pos, "%sLEAP", - pos == buf ? "" : " "); - if (ret < 0 || ret >= end - pos) { - end[-1] = '\0'; - return buf; - } - pos += ret; - } - - return buf; -} - - -#ifdef IEEE8021X_EAPOL -static int wpa_config_parse_eap(const struct parse_data *data, - struct wpa_ssid *ssid, int line, - const char *value) -{ - int last, errors = 0; - char *start, *end, *buf; - struct eap_method_type *methods = NULL, *tmp; - size_t num_methods = 0; - - 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'; - tmp = methods; - methods = os_realloc(methods, - (num_methods + 1) * sizeof(*methods)); - if (methods == NULL) { - os_free(tmp); - os_free(buf); - return -1; - } - methods[num_methods].method = eap_get_type( - start, &methods[num_methods].vendor); - if (methods[num_methods].vendor == EAP_VENDOR_IETF && - methods[num_methods].method == EAP_TYPE_NONE) { - wpa_printf(MSG_ERROR, "Line %d: unknown EAP method " - "'%s'", line, start); - wpa_printf(MSG_ERROR, "You may need to add support for" - " this EAP method during wpa_supplicant\n" - "build time configuration.\n" - "See README for more information."); - errors++; - } else if (methods[num_methods].vendor == EAP_VENDOR_IETF && - methods[num_methods].method == EAP_TYPE_LEAP) - ssid->leap++; - else - ssid->non_leap++; - num_methods++; - if (last) - break; - start = end + 1; - } - os_free(buf); - - tmp = methods; - methods = os_realloc(methods, (num_methods + 1) * sizeof(*methods)); - if (methods == NULL) { - os_free(tmp); - return -1; - } - methods[num_methods].vendor = EAP_VENDOR_IETF; - methods[num_methods].method = EAP_TYPE_NONE; - num_methods++; - - wpa_hexdump(MSG_MSGDUMP, "eap methods", - (u8 *) methods, num_methods * sizeof(*methods)); - ssid->eap_methods = methods; - return errors ? -1 : 0; -} - - -static char * wpa_config_write_eap(const struct parse_data *data, - struct wpa_ssid *ssid) -{ - int i, ret; - char *buf, *pos, *end; - const struct eap_method_type *eap_methods = ssid->eap_methods; - const char *name; - - if (eap_methods == NULL) - return NULL; - - pos = buf = os_zalloc(100); - if (buf == NULL) - return NULL; - end = buf + 100; - - for (i = 0; eap_methods[i].vendor != EAP_VENDOR_IETF || - eap_methods[i].method != EAP_TYPE_NONE; i++) { - name = eap_get_name(eap_methods[i].vendor, - eap_methods[i].method); - if (name) { - ret = os_snprintf(pos, end - pos, "%s%s", - pos == buf ? "" : " ", name); - if (ret < 0 || ret >= end - pos) - break; - pos += ret; - } - } - - end[-1] = '\0'; - - return buf; -} -#endif /* IEEE8021X_EAPOL */ - - -static int wpa_config_parse_wep_key(u8 *key, size_t *len, int line, - const char *value, int idx) -{ - char *buf, title[20]; - - buf = wpa_config_parse_string(value, len); - if (buf == NULL) { - wpa_printf(MSG_ERROR, "Line %d: Invalid WEP key %d '%s'.", - line, idx, value); - return -1; - } - if (*len > MAX_WEP_KEY_LEN) { - wpa_printf(MSG_ERROR, "Line %d: Too long WEP key %d '%s'.", - line, idx, value); - os_free(buf); - return -1; - } - os_memcpy(key, buf, *len); - os_free(buf); - os_snprintf(title, sizeof(title), "wep_key%d", idx); - wpa_hexdump_key(MSG_MSGDUMP, title, key, *len); - return 0; -} - - -static int wpa_config_parse_wep_key0(const struct parse_data *data, - struct wpa_ssid *ssid, int line, - const char *value) -{ - return wpa_config_parse_wep_key(ssid->wep_key[0], - &ssid->wep_key_len[0], line, - value, 0); -} - - -static int wpa_config_parse_wep_key1(const struct parse_data *data, - struct wpa_ssid *ssid, int line, - const char *value) -{ - return wpa_config_parse_wep_key(ssid->wep_key[1], - &ssid->wep_key_len[1], line, - value, 1); -} - - -static int wpa_config_parse_wep_key2(const struct parse_data *data, - struct wpa_ssid *ssid, int line, - const char *value) -{ - return wpa_config_parse_wep_key(ssid->wep_key[2], - &ssid->wep_key_len[2], line, - value, 2); -} - - -static int wpa_config_parse_wep_key3(const struct parse_data *data, - struct wpa_ssid *ssid, int line, - const char *value) -{ - return wpa_config_parse_wep_key(ssid->wep_key[3], - &ssid->wep_key_len[3], line, - value, 3); -} - - -static char * wpa_config_write_wep_key(struct wpa_ssid *ssid, int idx) -{ - if (ssid->wep_key_len[idx] == 0) - return NULL; - return wpa_config_write_string(ssid->wep_key[idx], - ssid->wep_key_len[idx]); -} - - -static char * wpa_config_write_wep_key0(const struct parse_data *data, - struct wpa_ssid *ssid) -{ - return wpa_config_write_wep_key(ssid, 0); -} - - -static char * wpa_config_write_wep_key1(const struct parse_data *data, - struct wpa_ssid *ssid) -{ - return wpa_config_write_wep_key(ssid, 1); -} - - -static char * wpa_config_write_wep_key2(const struct parse_data *data, - struct wpa_ssid *ssid) -{ - return wpa_config_write_wep_key(ssid, 2); -} - - -static char * wpa_config_write_wep_key3(const struct parse_data *data, - struct wpa_ssid *ssid) -{ - return wpa_config_write_wep_key(ssid, 3); -} - - -/* Helper macros for network block parser */ - -#ifdef OFFSET -#undef OFFSET -#endif /* OFFSET */ -/* OFFSET: Get offset of a variable within the wpa_ssid structure */ -#define OFFSET(v) ((void *) &((struct wpa_ssid *) 0)->v) - -/* STR: Define a string variable for an ASCII string; f = field name */ -#define _STR(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(f) -#define STR(f) _STR(f), NULL, NULL, NULL, 0 -#define STR_KEY(f) _STR(f), NULL, NULL, NULL, 1 - -/* STR_LEN: Define a string variable with a separate variable for storing the - * data length. Unlike STR(), this can be used to store arbitrary binary data - * (i.e., even nul termination character). */ -#define _STR_LEN(f) _STR(f), OFFSET(f ## _len) -#define STR_LEN(f) _STR_LEN(f), NULL, NULL, 0 -#define STR_LEN_KEY(f) _STR_LEN(f), NULL, NULL, 1 - -/* STR_RANGE: Like STR_LEN(), but with minimum and maximum allowed length - * explicitly specified. */ -#define _STR_RANGE(f, min, max) _STR_LEN(f), (void *) (min), (void *) (max) -#define STR_RANGE(f, min, max) _STR_RANGE(f, min, max), 0 -#define STR_RANGE_KEY(f, min, max) _STR_RANGE(f, min, max), 1 - -#define _INT(f) #f, wpa_config_parse_int, wpa_config_write_int, \ - OFFSET(f), (void *) 0 - -/* INT: Define an integer variable */ -#define INT(f) _INT(f), NULL, NULL, 0 - -/* INT_RANGE: Define an integer variable with allowed value range */ -#define INT_RANGE(f, min, max) _INT(f), (void *) (min), (void *) (max), 0 - -/* FUNC: Define a configuration variable that uses a custom function for - * parsing and writing the value. */ -#define _FUNC(f) #f, wpa_config_parse_ ## f, wpa_config_write_ ## f, \ - NULL, NULL, NULL, NULL -#define FUNC(f) _FUNC(f), 0 -#define FUNC_KEY(f) _FUNC(f), 1 - -/* - * Table of network configuration variables. This table is used to parse each - * network configuration variable, e.g., each line in wpa_supplicant.conf file - * that is inside a network block. - * - * This table is generated using the helper macros defined above and with - * generous help from the C pre-processor. The field name is stored as a string - * into .name and for STR and INT types, the offset of the target buffer within - * struct wpa_ssid is stored in .param1. .param2 (if not NULL) is similar - * offset to the field containing the length of the configuration variable. - * .param3 and .param4 can be used to mark the allowed range (length for STR - * and value for INT). - * - * For each configuration line in wpa_supplicant.conf, the parser goes through - * this table and select the entry that matches with the field name. The parser - * function (.parser) is then called to parse the actual value of the field. - * - * This kind of mechanism makes it easy to add new configuration parameters, - * since only one line needs to be added into this table and into the - * struct wpa_ssid definition if the new variable is either a string or - * integer. More complex types will need to use their own parser and writer - * functions. - */ -static const struct parse_data ssid_fields[] = { - { STR_RANGE(ssid, 0, MAX_SSID_LEN) }, - { INT_RANGE(scan_ssid, 0, 1) }, - { FUNC(bssid) }, - { FUNC_KEY(psk) }, - { FUNC(proto) }, - { FUNC(key_mgmt) }, - { FUNC(pairwise) }, - { FUNC(group) }, - { FUNC(auth_alg) }, -#ifdef IEEE8021X_EAPOL - { FUNC(eap) }, - { STR_LEN(identity) }, - { STR_LEN(anonymous_identity) }, - { STR_RANGE_KEY(eappsk, EAP_PSK_LEN_MIN, EAP_PSK_LEN_MAX) }, - { STR_LEN(nai) }, - { STR_LEN_KEY(password) }, - { STR(ca_cert) }, - { STR(ca_path) }, - { STR(client_cert) }, - { STR(private_key) }, - { STR_KEY(private_key_passwd) }, - { STR(dh_file) }, - { STR(subject_match) }, - { STR(altsubject_match) }, - { STR(ca_cert2) }, - { STR(ca_path2) }, - { STR(client_cert2) }, - { STR(private_key2) }, - { STR_KEY(private_key2_passwd) }, - { STR(dh_file2) }, - { STR(subject_match2) }, - { STR(altsubject_match2) }, - { STR(phase1) }, - { STR(phase2) }, - { STR(pcsc) }, - { STR_KEY(pin) }, - { STR(engine_id) }, - { STR(key_id) }, - { INT(engine) }, - { INT(eapol_flags) }, -#endif /* IEEE8021X_EAPOL */ - { FUNC_KEY(wep_key0) }, - { FUNC_KEY(wep_key1) }, - { FUNC_KEY(wep_key2) }, - { FUNC_KEY(wep_key3) }, - { INT(wep_tx_keyidx) }, - { INT(priority) }, -#ifdef IEEE8021X_EAPOL - { INT(eap_workaround) }, - { STR(pac_file) }, - { INT(fragment_size) }, -#endif /* IEEE8021X_EAPOL */ - { INT_RANGE(mode, 0, 1) }, - { INT_RANGE(proactive_key_caching, 0, 1) }, - { INT_RANGE(disabled, 0, 1) }, - { STR(id_str) }, -#ifdef CONFIG_IEEE80211W - { INT_RANGE(ieee80211w, 0, 2) }, -#endif /* CONFIG_IEEE80211W */ - { INT_RANGE(peerkey, 0, 1) }, - { INT_RANGE(mixed_cell, 0, 1) }, - { INT_RANGE(frequency, 0, 10000) } -}; - -#undef OFFSET -#undef _STR -#undef STR -#undef STR_KEY -#undef _STR_LEN -#undef STR_LEN -#undef STR_LEN_KEY -#undef _STR_RANGE -#undef STR_RANGE -#undef STR_RANGE_KEY -#undef _INT -#undef INT -#undef INT_RANGE -#undef _FUNC -#undef FUNC -#undef FUNC_KEY -#define NUM_SSID_FIELDS (sizeof(ssid_fields) / sizeof(ssid_fields[0])) - - -/** - * wpa_config_add_prio_network - Add a network to priority lists - * @config: Configuration data from wpa_config_read() - * @ssid: Pointer to the network configuration to be added to the list - * Returns: 0 on success, -1 on failure - * - * This function is used to add a network block to the priority list of - * networks. This must be called for each network when reading in the full - * configuration. In addition, this can be used indirectly when updating - * priorities by calling wpa_config_update_prio_list(). - */ -int wpa_config_add_prio_network(struct wpa_config *config, - struct wpa_ssid *ssid) -{ - int prio; - struct wpa_ssid *prev, **nlist; - - /* - * Add to an existing priority list if one is available for the - * configured priority level for this network. - */ - for (prio = 0; prio < config->num_prio; prio++) { - prev = config->pssid[prio]; - if (prev->priority == ssid->priority) { - while (prev->pnext) - prev = prev->pnext; - prev->pnext = ssid; - return 0; - } - } - - /* First network for this priority - add a new priority list */ - nlist = os_realloc(config->pssid, - (config->num_prio + 1) * sizeof(struct wpa_ssid *)); - if (nlist == NULL) - return -1; - - for (prio = 0; prio < config->num_prio; prio++) { - if (nlist[prio]->priority < ssid->priority) - break; - } - - os_memmove(&nlist[prio + 1], &nlist[prio], - (config->num_prio - prio) * sizeof(struct wpa_ssid *)); - - nlist[prio] = ssid; - config->num_prio++; - config->pssid = nlist; - - return 0; -} - - -/** - * wpa_config_update_prio_list - Update network priority list - * @config: Configuration data from wpa_config_read() - * Returns: 0 on success, -1 on failure - * - * This function is called to update the priority list of networks in the - * configuration when a network is being added or removed. This is also called - * if a priority for a network is changed. - */ -static int wpa_config_update_prio_list(struct wpa_config *config) -{ - struct wpa_ssid *ssid; - int ret = 0; - - os_free(config->pssid); - config->pssid = NULL; - config->num_prio = 0; - - ssid = config->ssid; - while (ssid) { - ssid->pnext = NULL; - if (wpa_config_add_prio_network(config, ssid) < 0) - ret = -1; - ssid = ssid->next; - } - - return ret; -} - - -/** - * wpa_config_free_ssid - Free network/ssid configuration data - * @ssid: Configuration data for the network - * - * This function frees all resources allocated for the network configuration - * data. - */ -void wpa_config_free_ssid(struct wpa_ssid *ssid) -{ - os_free(ssid->ssid); - os_free(ssid->passphrase); -#ifdef IEEE8021X_EAPOL - os_free(ssid->eap_methods); - os_free(ssid->identity); - os_free(ssid->anonymous_identity); - os_free(ssid->eappsk); - os_free(ssid->nai); - os_free(ssid->password); - os_free(ssid->ca_cert); - os_free(ssid->ca_path); - os_free(ssid->client_cert); - os_free(ssid->private_key); - os_free(ssid->private_key_passwd); - os_free(ssid->dh_file); - os_free(ssid->subject_match); - os_free(ssid->altsubject_match); - os_free(ssid->ca_cert2); - os_free(ssid->ca_path2); - os_free(ssid->client_cert2); - os_free(ssid->private_key2); - os_free(ssid->private_key2_passwd); - os_free(ssid->dh_file2); - os_free(ssid->subject_match2); - os_free(ssid->altsubject_match2); - os_free(ssid->phase1); - os_free(ssid->phase2); - os_free(ssid->pcsc); - os_free(ssid->pin); - os_free(ssid->engine_id); - os_free(ssid->key_id); - os_free(ssid->otp); - os_free(ssid->pending_req_otp); - os_free(ssid->pac_file); - os_free(ssid->new_password); -#endif /* IEEE8021X_EAPOL */ - os_free(ssid->id_str); - os_free(ssid); -} - - -/** - * wpa_config_free - Free configuration data - * @config: Configuration data from wpa_config_read() - * - * This function frees all resources allocated for the configuration data by - * wpa_config_read(). - */ -void wpa_config_free(struct wpa_config *config) -{ - struct wpa_config_blob *blob, *prevblob; - struct wpa_ssid *ssid, *prev = NULL; - ssid = config->ssid; - while (ssid) { - prev = ssid; - ssid = ssid->next; - wpa_config_free_ssid(prev); - } - - blob = config->blobs; - prevblob = NULL; - while (blob) { - prevblob = blob; - blob = blob->next; - wpa_config_free_blob(prevblob); - } - - os_free(config->ctrl_interface); - os_free(config->ctrl_interface_group); - os_free(config->opensc_engine_path); - os_free(config->pkcs11_engine_path); - os_free(config->pkcs11_module_path); - os_free(config->driver_param); - os_free(config->pssid); - os_free(config); -} - - -#ifdef IEEE8021X_EAPOL -/** - * wpa_config_allowed_eap_method - Check whether EAP method is allowed - * @ssid: Pointer to configuration data - * @vendor: Vendor-Id for expanded types or 0 = IETF for legacy types - * @method: EAP type - * Returns: 1 = allowed EAP method, 0 = not allowed - */ -int wpa_config_allowed_eap_method(struct wpa_ssid *ssid, int vendor, - u32 method) -{ - int i; - struct eap_method_type *m; - - if (ssid == NULL || ssid->eap_methods == NULL) - return 1; - - m = ssid->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; -} -#endif /* IEEE8021X_EAPOL */ - - -/** - * wpa_config_get_network - Get configured network based on id - * @config: Configuration data from wpa_config_read() - * @id: Unique network id to search for - * Returns: Network configuration or %NULL if not found - */ -struct wpa_ssid * wpa_config_get_network(struct wpa_config *config, int id) -{ - struct wpa_ssid *ssid; - - ssid = config->ssid; - while (ssid) { - if (id == ssid->id) - break; - ssid = ssid->next; - } - - return ssid; -} - - -/** - * wpa_config_add_network - Add a new network with empty configuration - * @config: Configuration data from wpa_config_read() - * Returns: The new network configuration or %NULL if operation failed - */ -struct wpa_ssid * wpa_config_add_network(struct wpa_config *config) -{ - int id; - struct wpa_ssid *ssid, *last = NULL; - - id = -1; - ssid = config->ssid; - while (ssid) { - if (ssid->id > id) - id = ssid->id; - last = ssid; - ssid = ssid->next; - } - id++; - - ssid = os_zalloc(sizeof(*ssid)); - if (ssid == NULL) - return NULL; - ssid->id = id; - if (last) - last->next = ssid; - else - config->ssid = ssid; - - wpa_config_update_prio_list(config); - - return ssid; -} - - -/** - * wpa_config_remove_network - Remove a configured network based on id - * @config: Configuration data from wpa_config_read() - * @id: Unique network id to search for - * Returns: 0 on success, or -1 if the network was not found - */ -int wpa_config_remove_network(struct wpa_config *config, int id) -{ - struct wpa_ssid *ssid, *prev = NULL; - - ssid = config->ssid; - while (ssid) { - if (id == ssid->id) - break; - prev = ssid; - ssid = ssid->next; - } - - if (ssid == NULL) - return -1; - - if (prev) - prev->next = ssid->next; - else - config->ssid = ssid->next; - - wpa_config_update_prio_list(config); - wpa_config_free_ssid(ssid); - return 0; -} - - -/** - * wpa_config_set_network_defaults - Set network default values - * @ssid: Pointer to network configuration data - */ -void wpa_config_set_network_defaults(struct wpa_ssid *ssid) -{ - ssid->proto = DEFAULT_PROTO; - ssid->pairwise_cipher = DEFAULT_PAIRWISE; - ssid->group_cipher = DEFAULT_GROUP; - ssid->key_mgmt = DEFAULT_KEY_MGMT; -#ifdef IEEE8021X_EAPOL - ssid->eapol_flags = DEFAULT_EAPOL_FLAGS; - ssid->eap_workaround = DEFAULT_EAP_WORKAROUND; - ssid->fragment_size = DEFAULT_FRAGMENT_SIZE; -#endif /* IEEE8021X_EAPOL */ -} - - -/** - * wpa_config_set - Set a variable in network configuration - * @ssid: Pointer to network configuration data - * @var: Variable name, e.g., "ssid" - * @value: Variable value - * @line: Line number in configuration file or 0 if not used - * Returns: 0 on success, -1 on failure - * - * This function can be used to set network configuration variables based on - * both the configuration file and management interface input. The value - * parameter must be in the same format as the text-based configuration file is - * using. For example, strings are using double quotation marks. - */ -int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value, - int line) -{ - size_t i; - int ret = 0; - - if (ssid == NULL || var == NULL || value == NULL) - return -1; - - for (i = 0; i < NUM_SSID_FIELDS; i++) { - const struct parse_data *field = &ssid_fields[i]; - if (os_strcmp(var, field->name) != 0) - continue; - - if (field->parser(field, ssid, line, value)) { - if (line) { - wpa_printf(MSG_ERROR, "Line %d: failed to " - "parse %s '%s'.", line, var, value); - } - ret = -1; - } - break; - } - if (i == NUM_SSID_FIELDS) { - if (line) { - wpa_printf(MSG_ERROR, "Line %d: unknown network field " - "'%s'.", line, var); - } - ret = -1; - } - - return ret; -} - - -/** - * wpa_config_get - Get a variable in network configuration - * @ssid: Pointer to network configuration data - * @var: Variable name, e.g., "ssid" - * Returns: Value of the variable or %NULL on failure - * - * This function can be used to get network configuration variables. The - * returned value is a copy of the configuration variable in text format, i.e,. - * the same format that the text-based configuration file and wpa_config_set() - * are using for the value. The caller is responsible for freeing the returned - * value. - */ -char * wpa_config_get(struct wpa_ssid *ssid, const char *var) -{ - size_t i; - - if (ssid == NULL || var == NULL) - return NULL; - - for (i = 0; i < NUM_SSID_FIELDS; i++) { - const struct parse_data *field = &ssid_fields[i]; - if (os_strcmp(var, field->name) == 0) - return field->writer(field, ssid); - } - - return NULL; -} - - -/** - * wpa_config_get_no_key - Get a variable in network configuration (no keys) - * @ssid: Pointer to network configuration data - * @var: Variable name, e.g., "ssid" - * Returns: Value of the variable or %NULL on failure - * - * This function can be used to get network configuration variable like - * wpa_config_get(). The only difference is that this functions does not expose - * key/password material from the configuration. In case a key/password field - * is requested, the returned value is an empty string or %NULL if the variable - * is not set or "*" if the variable is set (regardless of its value). The - * returned value is a copy of the configuration variable in text format, i.e,. - * the same format that the text-based configuration file and wpa_config_set() - * are using for the value. The caller is responsible for freeing the returned - * value. - */ -char * wpa_config_get_no_key(struct wpa_ssid *ssid, const char *var) -{ - size_t i; - - if (ssid == NULL || var == NULL) - return NULL; - - for (i = 0; i < NUM_SSID_FIELDS; i++) { - const struct parse_data *field = &ssid_fields[i]; - if (os_strcmp(var, field->name) == 0) { - char *res = field->writer(field, ssid); - if (field->key_data) { - if (res && res[0]) { - wpa_printf(MSG_DEBUG, "Do not allow " - "key_data field to be " - "exposed"); - os_free(res); - return os_strdup("*"); - } - - os_free(res); - return NULL; - } - return res; - } - } - - return NULL; -} - - -/** - * wpa_config_update_psk - Update WPA PSK based on passphrase and SSID - * @ssid: Pointer to network configuration data - * - * This function must be called to update WPA PSK when either SSID or the - * passphrase has changed for the network configuration. - */ -void wpa_config_update_psk(struct wpa_ssid *ssid) -{ - pbkdf2_sha1(ssid->passphrase, - (char *) ssid->ssid, ssid->ssid_len, 4096, - ssid->psk, PMK_LEN); - wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)", - ssid->psk, PMK_LEN); - ssid->psk_set = 1; -} - - -/** - * wpa_config_get_blob - Get a named configuration blob - * @config: Configuration data from wpa_config_read() - * @name: Name of the blob - * Returns: Pointer to blob data or %NULL if not found - */ -const struct wpa_config_blob * wpa_config_get_blob(struct wpa_config *config, - const char *name) -{ - struct wpa_config_blob *blob = config->blobs; - - while (blob) { - if (os_strcmp(blob->name, name) == 0) - return blob; - blob = blob->next; - } - return NULL; -} - - -/** - * wpa_config_set_blob - Set or add a named configuration blob - * @config: Configuration data from wpa_config_read() - * @blob: New value for the blob - * - * Adds a new configuration blob or replaces the current value of an existing - * blob. - */ -void wpa_config_set_blob(struct wpa_config *config, - struct wpa_config_blob *blob) -{ - wpa_config_remove_blob(config, blob->name); - blob->next = config->blobs; - config->blobs = blob; -} - - -/** - * wpa_config_free_blob - Free blob data - * @blob: Pointer to blob to be freed - */ -void wpa_config_free_blob(struct wpa_config_blob *blob) -{ - if (blob) { - os_free(blob->name); - os_free(blob->data); - os_free(blob); - } -} - - -/** - * wpa_config_remove_blob - Remove a named configuration blob - * @config: Configuration data from wpa_config_read() - * @name: Name of the blob to remove - * Returns: 0 if blob was removed or -1 if blob was not found - */ -int wpa_config_remove_blob(struct wpa_config *config, const char *name) -{ - struct wpa_config_blob *pos = config->blobs, *prev = NULL; - - while (pos) { - if (os_strcmp(pos->name, name) == 0) { - if (prev) - prev->next = pos->next; - else - config->blobs = pos->next; - wpa_config_free_blob(pos); - return 0; - } - prev = pos; - pos = pos->next; - } - - return -1; -} - - -/** - * wpa_config_alloc_empty - Allocate an empty configuration - * @ctrl_interface: Control interface parameters, e.g., path to UNIX domain - * socket - * @driver_param: Driver parameters - * Returns: Pointer to allocated configuration data or %NULL on failure - */ -struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface, - const char *driver_param) -{ - struct wpa_config *config; - - config = os_zalloc(sizeof(*config)); - if (config == NULL) - return NULL; - config->eapol_version = DEFAULT_EAPOL_VERSION; - config->ap_scan = DEFAULT_AP_SCAN; - config->fast_reauth = DEFAULT_FAST_REAUTH; - - if (ctrl_interface) - config->ctrl_interface = os_strdup(ctrl_interface); - if (driver_param) - config->driver_param = os_strdup(driver_param); - - return config; -} - - -#ifndef CONFIG_NO_STDOUT_DEBUG -/** - * wpa_config_debug_dump_networks - Debug dump of configured networks - * @config: Configuration data from wpa_config_read() - */ -void wpa_config_debug_dump_networks(struct wpa_config *config) -{ - int prio; - struct wpa_ssid *ssid; - - for (prio = 0; prio < config->num_prio; prio++) { - ssid = config->pssid[prio]; - wpa_printf(MSG_DEBUG, "Priority group %d", - ssid->priority); - while (ssid) { - wpa_printf(MSG_DEBUG, " id=%d ssid='%s'", - ssid->id, - wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); - ssid = ssid->pnext; - } - } -} -#endif /* CONFIG_NO_STDOUT_DEBUG */ diff --git a/contrib/wpa_supplicant/config.h b/contrib/wpa_supplicant/config.h deleted file mode 100644 index 3852f9274e2b..000000000000 --- a/contrib/wpa_supplicant/config.h +++ /dev/null @@ -1,339 +0,0 @@ -/* - * WPA Supplicant / Configuration file structures - * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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_H -#define CONFIG_H - -#define DEFAULT_EAPOL_VERSION 1 -#define DEFAULT_AP_SCAN 1 -#define DEFAULT_FAST_REAUTH 1 - -#include "config_ssid.h" - -/** - * 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; -}; - - -/** - * struct wpa_config - wpa_supplicant configuration data - * - * This data structure is presents the per-interface (radio) configuration - * data. In many cases, there is only one struct wpa_config instance, but if - * more than one network interface is being controlled, one instance is used - * for each. - */ -struct wpa_config { - /** - * ssid - Head of the global network list - * - * This is the head for the list of all the configured networks. - */ - struct wpa_ssid *ssid; - - /** - * pssid - Per-priority network lists (in priority order) - */ - struct wpa_ssid **pssid; - - /** - * num_prio - Number of different priorities used in the pssid lists - * - * This indicates how many per-priority network lists are included in - * pssid. - */ - int num_prio; - - /** - * eapol_version - IEEE 802.1X/EAPOL version number - * - * wpa_supplicant is implemented based on IEEE Std 802.1X-2004 which - * defines EAPOL version 2. However, there are many APs that do not - * handle the new version number correctly (they seem to drop the - * frames completely). In order to make wpa_supplicant interoperate - * with these APs, the version number is set to 1 by default. This - * configuration value can be used to set it to the new version (2). - */ - int eapol_version; - - /** - * ap_scan - AP scanning/selection - * - * By default, wpa_supplicant requests driver to perform AP - * scanning and then uses the scan results to select a - * suitable AP. Another alternative is to allow the driver to - * take care of AP scanning and selection and use - * wpa_supplicant just to process EAPOL frames based on IEEE - * 802.11 association information from the driver. - * - * 1: wpa_supplicant initiates scanning and AP selection (default). - * - * 0: Driver takes care of scanning, AP selection, and IEEE 802.11 - * association parameters (e.g., WPA IE generation); this mode can - * also be used with non-WPA drivers when using IEEE 802.1X mode; - * do not try to associate with APs (i.e., external program needs - * to control association). This mode must also be used when using - * wired Ethernet drivers. - * - * 2: like 0, but associate with APs using security policy and SSID - * (but not BSSID); this can be used, e.g., with ndiswrapper and NDIS - * drivers to enable operation with hidden SSIDs and optimized roaming; - * in this mode, the network blocks in the configuration are tried - * one by one until the driver reports successful association; each - * network block should have explicit security policy (i.e., only one - * option in the lists) for key_mgmt, pairwise, group, proto variables. - */ - int ap_scan; - - /** - * ctrl_interface - Parameters for the control interface - * - * If this is specified, %wpa_supplicant will open a control interface - * that is available for external programs to manage %wpa_supplicant. - * The meaning of this string depends on which control interface - * mechanism is used. For all cases, the existance of this parameter - * in configuration is used to determine whether the control interface - * is enabled. - * - * For UNIX domain sockets (default on Linux and BSD): This is a - * directory that will be created for UNIX domain sockets 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 %wpa_supplicant processes can be - * run at the same time if more than one interface is used. - * /var/run/wpa_supplicant is the recommended directory for sockets and - * by default, wpa_cli will use it when trying to connect with - * %wpa_supplicant. - * - * 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 - * %wpa_supplicant 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, %wpa_supplicant is configured to use gid - * 0 (root). If you want to allow non-root users to use the - * control 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. - * - * When configuring both the directory and group, use following format: - * DIR=/var/run/wpa_supplicant GROUP=wheel - * DIR=/var/run/wpa_supplicant GROUP=0 - * (group can be either group name or gid) - * - * For UDP connections (default on Windows): The value will be ignored. - * This variable is just used to select that the control interface is - * to be created. The value can be set to, e.g., udp - * (ctrl_interface=udp). - * - * For Windows Named Pipe: This value can be used to set the security - * descriptor for controlling access to the control interface. Security - * descriptor can be set using Security Descriptor String Format (see - * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthz/security/security_descriptor_string_format.asp). - * The descriptor string needs to be prefixed with SDDL=. For example, - * ctrl_interface=SDDL=D: would set an empty DACL (which will reject - * all connections). - */ - char *ctrl_interface; - - /** - * ctrl_interface_group - Control interface group (DEPRECATED) - * - * This variable is only used for backwards compatibility. Group for - * UNIX domain sockets should now be specified using GROUP=<group> in - * ctrl_interface variable. - */ - char *ctrl_interface_group; - - /** - * fast_reauth - EAP fast re-authentication (session resumption) - * - * By default, fast re-authentication is enabled for all EAP methods - * that support it. This variable can be used to disable fast - * re-authentication (by setting fast_reauth=0). Normally, there is no - * need to disable fast re-authentication. - */ - int fast_reauth; - - /** - * 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. - */ - 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. - */ - 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. - */ - char *pkcs11_module_path; - - /** - * driver_param - Driver interface parameters - * - * This text string is passed to the selected driver interface with the - * optional struct wpa_driver_ops::set_param() handler. This can be - * used to configure driver specific options without having to add new - * driver interface functionality. - */ - char *driver_param; - - /** - * dot11RSNAConfigPMKLifetime - Maximum lifetime of a PMK - * - * dot11 MIB variable for the maximum lifetime of a PMK in the PMK - * cache (unit: seconds). - */ - unsigned int dot11RSNAConfigPMKLifetime; - - /** - * dot11RSNAConfigPMKReauthThreshold - PMK re-authentication threshold - * - * dot11 MIB variable for the percentage of the PMK lifetime - * that should expire before an IEEE 802.1X reauthentication occurs. - */ - unsigned int dot11RSNAConfigPMKReauthThreshold; - - /** - * dot11RSNAConfigSATimeout - Security association timeout - * - * dot11 MIB variable for the maximum time a security association - * shall take to set up (unit: seconds). - */ - unsigned int dot11RSNAConfigSATimeout; - - /** - * update_config - Is wpa_supplicant allowed to update configuration - * - * This variable control whether wpa_supplicant is allow to re-write - * its configuration with wpa_config_write(). If this is zero, - * configuration data is only changed in memory and the external data - * is not overriden. If this is non-zero, wpa_supplicant will update - * the configuration data (e.g., a file) whenever configuration is - * changed. This update may replace the old configuration which can - * remove comments from it in case of a text file configuration. - */ - int update_config; - - /** - * blobs - Configuration blobs - */ - struct wpa_config_blob *blobs; -}; - - -/* Prototypes for common functions from config.c */ - -void wpa_config_free(struct wpa_config *ssid); -void wpa_config_free_ssid(struct wpa_ssid *ssid); -struct wpa_ssid * wpa_config_get_network(struct wpa_config *config, int id); -struct wpa_ssid * wpa_config_add_network(struct wpa_config *config); -int wpa_config_remove_network(struct wpa_config *config, int id); -void wpa_config_set_network_defaults(struct wpa_ssid *ssid); -int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value, - int line); -char * wpa_config_get(struct wpa_ssid *ssid, const char *var); -char * wpa_config_get_no_key(struct wpa_ssid *ssid, const char *var); -void wpa_config_update_psk(struct wpa_ssid *ssid); -int wpa_config_add_prio_network(struct wpa_config *config, - struct wpa_ssid *ssid); - -const struct wpa_config_blob * wpa_config_get_blob(struct wpa_config *config, - const char *name); -void wpa_config_set_blob(struct wpa_config *config, - struct wpa_config_blob *blob); -void wpa_config_free_blob(struct wpa_config_blob *blob); -int wpa_config_remove_blob(struct wpa_config *config, const char *name); -struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface, - const char *driver_param); -#ifndef CONFIG_NO_STDOUT_DEBUG -void wpa_config_debug_dump_networks(struct wpa_config *config); -#else /* CONFIG_NO_STDOUT_DEBUG */ -#define wpa_config_debug_dump_networks(c) do { } while (0) -#endif /* CONFIG_NO_STDOUT_DEBUG */ - - -/* Prototypes for backend specific functions from the selected config_*.c */ - -/** - * wpa_config_read - Read and parse configuration database - * @name: Name of the configuration (e.g., path and file name for the - * configuration file) - * Returns: Pointer to allocated configuration data or %NULL on failure - * - * This function reads configuration data, parses its contents, and allocates - * data structures needed for storing configuration information. The allocated - * data can be freed with wpa_config_free(). - * - * Each configuration backend needs to implement this function. - */ -struct wpa_config * wpa_config_read(const char *name); - -/** - * wpa_config_write - Write or update configuration data - * @name: Name of the configuration (e.g., path and file name for the - * configuration file) - * @config: Configuration data from wpa_config_read() - * Returns: 0 on success, -1 on failure - * - * This function write all configuration data into an external database (e.g., - * a text file) in a format that can be read with wpa_config_read(). This can - * be used to allow wpa_supplicant to update its configuration, e.g., when a - * new network is added or a password is changed. - * - * Each configuration backend needs to implement this function. - */ -int wpa_config_write(const char *name, struct wpa_config *config); - -#endif /* CONFIG_H */ diff --git a/contrib/wpa_supplicant/config_file.c b/contrib/wpa_supplicant/config_file.c deleted file mode 100644 index 757a1b8b1d6b..000000000000 --- a/contrib/wpa_supplicant/config_file.c +++ /dev/null @@ -1,724 +0,0 @@ -/* - * WPA Supplicant / Configuration backend: text file - * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 configuration backend for text files. All the - * configuration information is stored in a text file that uses a format - * described in the sample configuration file, wpa_supplicant.conf. - */ - -#include "includes.h" - -#include "common.h" -#include "config.h" -#include "base64.h" -#include "eap_methods.h" - - -/** - * wpa_config_get_line - Read the next configuration file line - * @s: Buffer for the line - * @size: The buffer length - * @stream: File stream to read from - * @line: Pointer to a variable storing the file line number - * @_pos: Buffer for the pointer to the beginning of data on the text line or - * %NULL if not needed (returned value used instead) - * Returns: Pointer to the beginning of data on the text line or %NULL if no - * more text lines are available. - * - * This function reads the next non-empty line from the configuration file and - * removes comments. The returned string is guaranteed to be null-terminated. - */ -static char * wpa_config_get_line(char *s, int size, FILE *stream, int *line, - char **_pos) -{ - char *pos, *end, *sstart; - - while (fgets(s, size, stream)) { - (*line)++; - s[size - 1] = '\0'; - pos = s; - - /* Skip white space from the beginning of line. */ - while (*pos == ' ' || *pos == '\t' || *pos == '\r') - pos++; - - /* Skip comment lines and empty lines */ - if (*pos == '#' || *pos == '\n' || *pos == '\0') - continue; - - /* - * Remove # comments unless they are within a double quoted - * string. - */ - sstart = os_strchr(pos, '"'); - if (sstart) - sstart = os_strrchr(sstart + 1, '"'); - if (!sstart) - sstart = pos; - end = os_strchr(sstart, '#'); - if (end) - *end-- = '\0'; - else - end = pos + os_strlen(pos) - 1; - - /* Remove trailing white space. */ - while (end > pos && - (*end == '\n' || *end == ' ' || *end == '\t' || - *end == '\r')) - *end-- = '\0'; - - if (*pos == '\0') - continue; - - if (_pos) - *_pos = pos; - return pos; - } - - if (_pos) - *_pos = NULL; - return NULL; -} - - -static int wpa_config_validate_network(struct wpa_ssid *ssid, int line) -{ - int errors = 0; - - if (ssid->passphrase) { - if (ssid->psk_set) { - wpa_printf(MSG_ERROR, "Line %d: both PSK and " - "passphrase configured.", line); - errors++; - } - wpa_config_update_psk(ssid); - } - - if ((ssid->key_mgmt & WPA_KEY_MGMT_PSK) && !ssid->psk_set) { - wpa_printf(MSG_ERROR, "Line %d: WPA-PSK accepted for key " - "management, but no PSK configured.", line); - errors++; - } - - if ((ssid->group_cipher & WPA_CIPHER_CCMP) && - !(ssid->pairwise_cipher & WPA_CIPHER_CCMP) && - !(ssid->pairwise_cipher & WPA_CIPHER_NONE)) { - /* Group cipher cannot be stronger than the pairwise cipher. */ - wpa_printf(MSG_DEBUG, "Line %d: removed CCMP from group cipher" - " list since it was not allowed for pairwise " - "cipher", line); - ssid->group_cipher &= ~WPA_CIPHER_CCMP; - } - - return errors; -} - - -static struct wpa_ssid * wpa_config_read_network(FILE *f, int *line, int id) -{ - struct wpa_ssid *ssid; - int errors = 0, end = 0; - char buf[256], *pos, *pos2; - - wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new network block", - *line); - ssid = os_zalloc(sizeof(*ssid)); - if (ssid == NULL) - return NULL; - ssid->id = id; - - wpa_config_set_network_defaults(ssid); - - while (wpa_config_get_line(buf, sizeof(buf), f, line, &pos)) { - if (os_strcmp(pos, "}") == 0) { - end = 1; - break; - } - - pos2 = os_strchr(pos, '='); - if (pos2 == NULL) { - wpa_printf(MSG_ERROR, "Line %d: Invalid SSID line " - "'%s'.", *line, pos); - errors++; - continue; - } - - *pos2++ = '\0'; - if (*pos2 == '"') { - if (os_strchr(pos2 + 1, '"') == NULL) { - wpa_printf(MSG_ERROR, "Line %d: invalid " - "quotation '%s'.", *line, pos2); - errors++; - continue; - } - } - - if (wpa_config_set(ssid, pos, pos2, *line) < 0) - errors++; - } - - if (!end) { - wpa_printf(MSG_ERROR, "Line %d: network block was not " - "terminated properly.", *line); - errors++; - } - - errors += wpa_config_validate_network(ssid, *line); - - if (errors) { - wpa_config_free_ssid(ssid); - ssid = NULL; - } - - return ssid; -} - - -static struct wpa_config_blob * wpa_config_read_blob(FILE *f, int *line, - const char *name) -{ - struct wpa_config_blob *blob; - char buf[256], *pos; - unsigned char *encoded = NULL, *nencoded; - int end = 0; - size_t encoded_len = 0, len; - - wpa_printf(MSG_MSGDUMP, "Line: %d - start of a new named blob '%s'", - *line, name); - - while (wpa_config_get_line(buf, sizeof(buf), f, line, &pos)) { - if (os_strcmp(pos, "}") == 0) { - end = 1; - break; - } - - len = os_strlen(pos); - nencoded = os_realloc(encoded, encoded_len + len); - if (nencoded == NULL) { - wpa_printf(MSG_ERROR, "Line %d: not enough memory for " - "blob", *line); - os_free(encoded); - return NULL; - } - encoded = nencoded; - os_memcpy(encoded + encoded_len, pos, len); - encoded_len += len; - } - - if (!end) { - wpa_printf(MSG_ERROR, "Line %d: blob was not terminated " - "properly", *line); - os_free(encoded); - return NULL; - } - - blob = os_zalloc(sizeof(*blob)); - if (blob == NULL) { - os_free(encoded); - return NULL; - } - blob->name = os_strdup(name); - blob->data = base64_decode(encoded, encoded_len, &blob->len); - os_free(encoded); - - if (blob->name == NULL || blob->data == NULL) { - wpa_config_free_blob(blob); - return NULL; - } - - return blob; -} - - -struct wpa_config * wpa_config_read(const char *name) -{ - FILE *f; - char buf[256], *pos; - int errors = 0, line = 0; - struct wpa_ssid *ssid, *tail = NULL, *head = NULL; - struct wpa_config *config; - int id = 0; - - config = wpa_config_alloc_empty(NULL, NULL); - if (config == NULL) - return NULL; - wpa_printf(MSG_DEBUG, "Reading configuration file '%s'", name); - f = fopen(name, "r"); - if (f == NULL) { - os_free(config); - return NULL; - } - - while (wpa_config_get_line(buf, sizeof(buf), f, &line, &pos)) { - if (os_strcmp(pos, "network={") == 0) { - ssid = wpa_config_read_network(f, &line, id++); - if (ssid == NULL) { - wpa_printf(MSG_ERROR, "Line %d: failed to " - "parse network block.", line); - errors++; - continue; - } - if (head == NULL) { - head = tail = ssid; - } else { - tail->next = ssid; - tail = ssid; - } - if (wpa_config_add_prio_network(config, ssid)) { - wpa_printf(MSG_ERROR, "Line %d: failed to add " - "network block to priority list.", - line); - errors++; - continue; - } - } else if (os_strncmp(pos, "blob-base64-", 12) == 0) { - char *bname = pos + 12, *name_end; - struct wpa_config_blob *blob; - - name_end = os_strchr(bname, '='); - if (name_end == NULL) { - wpa_printf(MSG_ERROR, "Line %d: no blob name " - "terminator", line); - errors++; - continue; - } - *name_end = '\0'; - - blob = wpa_config_read_blob(f, &line, bname); - if (blob == NULL) { - wpa_printf(MSG_ERROR, "Line %d: failed to read" - " blob %s", line, bname); - errors++; - continue; - } - wpa_config_set_blob(config, blob); -#ifdef CONFIG_CTRL_IFACE - } else if (os_strncmp(pos, "ctrl_interface=", 15) == 0) { - os_free(config->ctrl_interface); - config->ctrl_interface = os_strdup(pos + 15); - wpa_printf(MSG_DEBUG, "ctrl_interface='%s'", - config->ctrl_interface); - } else if (os_strncmp(pos, "ctrl_interface_group=", 21) == 0) { - os_free(config->ctrl_interface_group); - config->ctrl_interface_group = os_strdup(pos + 21); - wpa_printf(MSG_DEBUG, "ctrl_interface_group='%s' " - "(DEPRECATED)", - config->ctrl_interface_group); -#endif /* CONFIG_CTRL_IFACE */ - } else if (os_strncmp(pos, "eapol_version=", 14) == 0) { - config->eapol_version = atoi(pos + 14); - if (config->eapol_version < 1 || - config->eapol_version > 2) { - wpa_printf(MSG_ERROR, "Line %d: Invalid EAPOL " - "version (%d): '%s'.", - line, config->eapol_version, pos); - errors++; - continue; - } - wpa_printf(MSG_DEBUG, "eapol_version=%d", - config->eapol_version); - } else if (os_strncmp(pos, "ap_scan=", 8) == 0) { - config->ap_scan = atoi(pos + 8); - wpa_printf(MSG_DEBUG, "ap_scan=%d", config->ap_scan); - } else if (os_strncmp(pos, "fast_reauth=", 12) == 0) { - config->fast_reauth = atoi(pos + 12); - wpa_printf(MSG_DEBUG, "fast_reauth=%d", - config->fast_reauth); - } else if (os_strncmp(pos, "opensc_engine_path=", 19) == 0) { - os_free(config->opensc_engine_path); - config->opensc_engine_path = os_strdup(pos + 19); - wpa_printf(MSG_DEBUG, "opensc_engine_path='%s'", - config->opensc_engine_path); - } else if (os_strncmp(pos, "pkcs11_engine_path=", 19) == 0) { - os_free(config->pkcs11_engine_path); - config->pkcs11_engine_path = os_strdup(pos + 19); - wpa_printf(MSG_DEBUG, "pkcs11_engine_path='%s'", - config->pkcs11_engine_path); - } else if (os_strncmp(pos, "pkcs11_module_path=", 19) == 0) { - os_free(config->pkcs11_module_path); - config->pkcs11_module_path = os_strdup(pos + 19); - wpa_printf(MSG_DEBUG, "pkcs11_module_path='%s'", - config->pkcs11_module_path); - } else if (os_strncmp(pos, "driver_param=", 13) == 0) { - os_free(config->driver_param); - config->driver_param = os_strdup(pos + 13); - wpa_printf(MSG_DEBUG, "driver_param='%s'", - config->driver_param); - } else if (os_strncmp(pos, "dot11RSNAConfigPMKLifetime=", 27) - == 0) { - config->dot11RSNAConfigPMKLifetime = atoi(pos + 27); - wpa_printf(MSG_DEBUG, "dot11RSNAConfigPMKLifetime=%d", - config->dot11RSNAConfigPMKLifetime); - } else if (os_strncmp(pos, - "dot11RSNAConfigPMKReauthThreshold=", 34) - == 0) { - config->dot11RSNAConfigPMKReauthThreshold = - atoi(pos + 34); - wpa_printf(MSG_DEBUG, - "dot11RSNAConfigPMKReauthThreshold=%d", - config->dot11RSNAConfigPMKReauthThreshold); - } else if (os_strncmp(pos, "dot11RSNAConfigSATimeout=", 25) == - 0) { - config->dot11RSNAConfigSATimeout = atoi(pos + 25); - wpa_printf(MSG_DEBUG, "dot11RSNAConfigSATimeout=%d", - config->dot11RSNAConfigSATimeout); - } else if (os_strncmp(pos, "update_config=", 14) == 0) { - config->update_config = atoi(pos + 14); - wpa_printf(MSG_DEBUG, "update_config=%d", - config->update_config); - } else if (os_strncmp(pos, "load_dynamic_eap=", 17) == 0) { - char *so = pos + 17; - int ret; - wpa_printf(MSG_DEBUG, "load_dynamic_eap=%s", so); - ret = eap_peer_method_load(so); - if (ret == -2) { - wpa_printf(MSG_DEBUG, "This EAP type was " - "already loaded - not reloading."); - } else if (ret) { - wpa_printf(MSG_ERROR, "Line %d: Failed to " - "load dynamic EAP method '%s'.", - line, so); - errors++; - } - } else { - wpa_printf(MSG_ERROR, "Line %d: Invalid configuration " - "line '%s'.", line, pos); - errors++; - continue; - } - } - - fclose(f); - - config->ssid = head; - wpa_config_debug_dump_networks(config); - - if (errors) { - wpa_config_free(config); - config = NULL; - head = NULL; - } - - return config; -} - - -static void write_str(FILE *f, const char *field, struct wpa_ssid *ssid) -{ - char *value = wpa_config_get(ssid, field); - if (value == NULL) - return; - fprintf(f, "\t%s=%s\n", field, value); - os_free(value); -} - - -static void write_int(FILE *f, const char *field, int value, int def) -{ - if (value == def) - return; - fprintf(f, "\t%s=%d\n", field, value); -} - - -static void write_bssid(FILE *f, struct wpa_ssid *ssid) -{ - char *value = wpa_config_get(ssid, "bssid"); - if (value == NULL) - return; - fprintf(f, "\tbssid=%s\n", value); - os_free(value); -} - - -static void write_psk(FILE *f, struct wpa_ssid *ssid) -{ - char *value = wpa_config_get(ssid, "psk"); - if (value == NULL) - return; - fprintf(f, "\tpsk=%s\n", value); - os_free(value); -} - - -static void write_proto(FILE *f, struct wpa_ssid *ssid) -{ - char *value; - - if (ssid->proto == DEFAULT_PROTO) - return; - - value = wpa_config_get(ssid, "proto"); - if (value == NULL) - return; - if (value[0]) - fprintf(f, "\tproto=%s\n", value); - os_free(value); -} - - -static void write_key_mgmt(FILE *f, struct wpa_ssid *ssid) -{ - char *value; - - if (ssid->key_mgmt == DEFAULT_KEY_MGMT) - return; - - value = wpa_config_get(ssid, "key_mgmt"); - if (value == NULL) - return; - if (value[0]) - fprintf(f, "\tkey_mgmt=%s\n", value); - os_free(value); -} - - -static void write_pairwise(FILE *f, struct wpa_ssid *ssid) -{ - char *value; - - if (ssid->pairwise_cipher == DEFAULT_PAIRWISE) - return; - - value = wpa_config_get(ssid, "pairwise"); - if (value == NULL) - return; - if (value[0]) - fprintf(f, "\tpairwise=%s\n", value); - os_free(value); -} - - -static void write_group(FILE *f, struct wpa_ssid *ssid) -{ - char *value; - - if (ssid->group_cipher == DEFAULT_GROUP) - return; - - value = wpa_config_get(ssid, "group"); - if (value == NULL) - return; - if (value[0]) - fprintf(f, "\tgroup=%s\n", value); - os_free(value); -} - - -static void write_auth_alg(FILE *f, struct wpa_ssid *ssid) -{ - char *value; - - if (ssid->auth_alg == 0) - return; - - value = wpa_config_get(ssid, "auth_alg"); - if (value == NULL) - return; - if (value[0]) - fprintf(f, "\tauth_alg=%s\n", value); - os_free(value); -} - - -#ifdef IEEE8021X_EAPOL -static void write_eap(FILE *f, struct wpa_ssid *ssid) -{ - char *value; - - value = wpa_config_get(ssid, "eap"); - if (value == NULL) - return; - - if (value[0]) - fprintf(f, "\teap=%s\n", value); - os_free(value); -} -#endif /* IEEE8021X_EAPOL */ - - -static void write_wep_key(FILE *f, int idx, struct wpa_ssid *ssid) -{ - char field[20], *value; - - os_snprintf(field, sizeof(field), "wep_key%d", idx); - value = wpa_config_get(ssid, field); - if (value) { - fprintf(f, "\t%s=%s\n", field, value); - os_free(value); - } -} - - -static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) -{ - int i; - -#define STR(t) write_str(f, #t, ssid) -#define INT(t) write_int(f, #t, ssid->t, 0) -#define INT_DEF(t, def) write_int(f, #t, ssid->t, def) - - STR(ssid); - INT(scan_ssid); - write_bssid(f, ssid); - write_psk(f, ssid); - write_proto(f, ssid); - write_key_mgmt(f, ssid); - write_pairwise(f, ssid); - write_group(f, ssid); - write_auth_alg(f, ssid); -#ifdef IEEE8021X_EAPOL - write_eap(f, ssid); - STR(identity); - STR(anonymous_identity); - STR(eappsk); - STR(nai); - STR(password); - STR(ca_cert); - STR(ca_path); - STR(client_cert); - STR(private_key); - STR(private_key_passwd); - STR(dh_file); - STR(subject_match); - STR(altsubject_match); - STR(ca_cert2); - STR(ca_path2); - STR(client_cert2); - STR(private_key2); - STR(private_key2_passwd); - STR(dh_file2); - STR(subject_match2); - STR(altsubject_match2); - STR(phase1); - STR(phase2); - STR(pcsc); - STR(pin); - STR(engine_id); - STR(key_id); - INT(engine); - INT_DEF(eapol_flags, DEFAULT_EAPOL_FLAGS); -#endif /* IEEE8021X_EAPOL */ - for (i = 0; i < 4; i++) - write_wep_key(f, i, ssid); - INT(wep_tx_keyidx); - INT(priority); -#ifdef IEEE8021X_EAPOL - INT_DEF(eap_workaround, DEFAULT_EAP_WORKAROUND); - STR(pac_file); - INT_DEF(fragment_size, DEFAULT_FRAGMENT_SIZE); -#endif /* IEEE8021X_EAPOL */ - INT(mode); - INT(proactive_key_caching); - INT(disabled); - INT(peerkey); -#ifdef CONFIG_IEEE80211W - INT(ieee80211w); -#endif /* CONFIG_IEEE80211W */ - STR(id_str); - -#undef STR -#undef INT -#undef INT_DEF -} - - -static int wpa_config_write_blob(FILE *f, struct wpa_config_blob *blob) -{ - unsigned char *encoded; - - encoded = base64_encode(blob->data, blob->len, NULL); - if (encoded == NULL) - return -1; - - fprintf(f, "\nblob-base64-%s={\n%s}\n", blob->name, encoded); - os_free(encoded); - return 0; -} - - -static void wpa_config_write_global(FILE *f, struct wpa_config *config) -{ -#ifdef CONFIG_CTRL_IFACE - if (config->ctrl_interface) - fprintf(f, "ctrl_interface=%s\n", config->ctrl_interface); - if (config->ctrl_interface_group) - fprintf(f, "ctrl_interface_group=%s\n", - config->ctrl_interface_group); -#endif /* CONFIG_CTRL_IFACE */ - if (config->eapol_version != DEFAULT_EAPOL_VERSION) - fprintf(f, "eapol_version=%d\n", config->eapol_version); - if (config->ap_scan != DEFAULT_AP_SCAN) - fprintf(f, "ap_scan=%d\n", config->ap_scan); - if (config->fast_reauth != DEFAULT_FAST_REAUTH) - fprintf(f, "fast_reauth=%d\n", config->fast_reauth); - if (config->opensc_engine_path) - fprintf(f, "opensc_engine_path=%s\n", - config->opensc_engine_path); - if (config->pkcs11_engine_path) - fprintf(f, "pkcs11_engine_path=%s\n", - config->pkcs11_engine_path); - if (config->pkcs11_module_path) - fprintf(f, "pkcs11_module_path=%s\n", - config->pkcs11_module_path); - if (config->driver_param) - fprintf(f, "driver_param=%s\n", config->driver_param); - if (config->dot11RSNAConfigPMKLifetime) - fprintf(f, "dot11RSNAConfigPMKLifetime=%d\n", - config->dot11RSNAConfigPMKLifetime); - if (config->dot11RSNAConfigPMKReauthThreshold) - fprintf(f, "dot11RSNAConfigPMKReauthThreshold=%d\n", - config->dot11RSNAConfigPMKReauthThreshold); - if (config->dot11RSNAConfigSATimeout) - fprintf(f, "dot11RSNAConfigSATimeout=%d\n", - config->dot11RSNAConfigSATimeout); - if (config->update_config) - fprintf(f, "update_config=%d\n", config->update_config); -} - - -int wpa_config_write(const char *name, struct wpa_config *config) -{ - FILE *f; - struct wpa_ssid *ssid; - struct wpa_config_blob *blob; - int ret = 0; - - wpa_printf(MSG_DEBUG, "Writing configuration file '%s'", name); - - f = fopen(name, "w"); - if (f == NULL) { - wpa_printf(MSG_DEBUG, "Failed to open '%s' for writing", name); - return -1; - } - - wpa_config_write_global(f, config); - - for (ssid = config->ssid; ssid; ssid = ssid->next) { - fprintf(f, "\nnetwork={\n"); - wpa_config_write_network(f, ssid); - fprintf(f, "}\n"); - } - - for (blob = config->blobs; blob; blob = blob->next) { - ret = wpa_config_write_blob(f, blob); - if (ret) - break; - } - - fclose(f); - - wpa_printf(MSG_DEBUG, "Configuration file '%s' written %ssuccessfully", - name, ret ? "un" : ""); - return ret; -} diff --git a/contrib/wpa_supplicant/config_none.c b/contrib/wpa_supplicant/config_none.c deleted file mode 100644 index 2e9ccc0a2835..000000000000 --- a/contrib/wpa_supplicant/config_none.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * WPA Supplicant / Configuration backend: empty starting point - * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 dummy example of a configuration backend. None of the - * functions are actually implemented so this can be used as a simple - * compilation test or a starting point for a new configuration backend. - */ - -#include "includes.h" - -#include "common.h" -#include "config.h" -#include "base64.h" - - -struct wpa_config * wpa_config_read(const char *name) -{ - struct wpa_config *config; - - config = wpa_config_alloc_empty(NULL, NULL); - if (config == NULL) - return NULL; - /* TODO: fill in configuration data */ - return config; -} - - -int wpa_config_write(const char *name, struct wpa_config *config) -{ - struct wpa_ssid *ssid; - struct wpa_config_blob *blob; - - wpa_printf(MSG_DEBUG, "Writing configuration file '%s'", name); - - /* TODO: write global config parameters */ - - - for (ssid = config->ssid; ssid; ssid = ssid->next) { - /* TODO: write networks */ - } - - for (blob = config->blobs; blob; blob = blob->next) { - /* TODO: write blobs */ - } - - return 0; -} diff --git a/contrib/wpa_supplicant/config_ssid.h b/contrib/wpa_supplicant/config_ssid.h deleted file mode 100644 index 393f7506ce39..000000000000 --- a/contrib/wpa_supplicant/config_ssid.h +++ /dev/null @@ -1,871 +0,0 @@ -/* - * WPA Supplicant / Network configuration structures - * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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_SSID_H -#define CONFIG_SSID_H - -#ifndef BIT -#define BIT(n) (1 << (n)) -#endif - -#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_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 MAX_SSID_LEN 32 -#define PMK_LEN 32 -#define EAP_PSK_LEN_MIN 16 -#define EAP_PSK_LEN_MAX 32 - - -#define DEFAULT_EAP_WORKAROUND ((unsigned int) -1) -#define DEFAULT_EAPOL_FLAGS (EAPOL_FLAG_REQUIRE_KEY_UNICAST | \ - EAPOL_FLAG_REQUIRE_KEY_BROADCAST) -#define DEFAULT_PROTO (WPA_PROTO_WPA | WPA_PROTO_RSN) -#define DEFAULT_KEY_MGMT (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_IEEE8021X) -#define DEFAULT_PAIRWISE (WPA_CIPHER_CCMP | WPA_CIPHER_TKIP) -#define DEFAULT_GROUP (WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | \ - WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40) -#define DEFAULT_FRAGMENT_SIZE 1398 - -/** - * struct wpa_ssid - Network configuration data - * - * This structure includes all the configuration variables for a network. This - * data is included in the per-interface configuration data as an element of - * the network list, struct wpa_config::ssid. Each network block in the - * configuration is mapped to a struct wpa_ssid instance. - */ -struct wpa_ssid { - /** - * next - Next network in global list - * - * This pointer can be used to iterate over all networks. The head of - * this list is stored in the ssid field of struct wpa_config. - */ - struct wpa_ssid *next; - - /** - * pnext - Next network in per-priority list - * - * This pointer can be used to iterate over all networks in the same - * priority class. The heads of these list are stored in the pssid - * fields of struct wpa_config. - */ - struct wpa_ssid *pnext; - - /** - * id - Unique id for the network - * - * This identifier is used as a unique identifier for each network - * block when using the control interface. Each network is allocated an - * id when it is being created, either when reading the configuration - * file or when a new network is added through the control interface. - */ - int id; - - /** - * priority - Priority group - * - * By default, all networks will get same priority group (0). If some - * of the networks are more desirable, this field can be used to change - * the order in which wpa_supplicant goes through the networks when - * selecting a BSS. The priority groups will be iterated in decreasing - * priority (i.e., the larger the priority value, the sooner the - * network is matched against the scan results). Within each priority - * group, networks will be selected based on security policy, signal - * strength, etc. - * - * Please note that AP scanning with scan_ssid=1 and ap_scan=2 mode are - * not using this priority to select the order for scanning. Instead, - * they try the networks in the order that used in the configuration - * file. - */ - int priority; - - /** - * ssid - Service set identifier (network name) - * - * This is the SSID for the network. For wireless interfaces, this is - * used to select which network will be used. If set to %NULL (or - * ssid_len=0), any SSID can be used. For wired interfaces, this must - * be set to %NULL. Note: SSID may contain any characters, even nul - * (ASCII 0) and as such, this should not be assumed to be a nul - * terminated string. ssid_len defines how many characters are valid - * and the ssid field is not guaranteed to be nul terminated. - */ - u8 *ssid; - - /** - * ssid_len - Length of the SSID - */ - size_t ssid_len; - - /** - * bssid - BSSID - * - * If set, this network block is used only when associating with the AP - * using the configured BSSID - */ - u8 bssid[ETH_ALEN]; - - /** - * bssid_set - Whether BSSID is configured for this network - */ - int bssid_set; - - /** - * psk - WPA pre-shared key (256 bits) - */ - u8 psk[PMK_LEN]; - - /** - * psk_set - Whether PSK field is configured - */ - int psk_set; - - /** - * passphrase - WPA ASCII passphrase - * - * If this is set, psk will be generated using the SSID and passphrase - * configured for the network. ASCII passphrase must be between 8 and - * 63 characters (inclusive). - */ - char *passphrase; - - /** - * pairwise_cipher - Bitfield of allowed pairwise ciphers, WPA_CIPHER_* - */ - int pairwise_cipher; - - /** - * group_cipher - Bitfield of allowed group ciphers, WPA_CIPHER_* - */ - int group_cipher; - - /** - * key_mgmt - Bitfield of allowed key management protocols - * - * WPA_KEY_MGMT_* - */ - int key_mgmt; - - /** - * proto - Bitfield of allowed protocols, WPA_PROTO_* - */ - int proto; - - /** - * auth_alg - Bitfield of allowed authentication algorithms - * - * WPA_AUTH_ALG_* - */ - int auth_alg; - - /** - * scan_ssid - Scan this SSID with Probe Requests - * - * scan_ssid can be used to scan for APs using hidden SSIDs. - * Note: Many drivers do not support this. ap_mode=2 can be used with - * such drivers to use hidden SSIDs. - */ - int scan_ssid; - -#ifdef IEEE8021X_EAPOL - - /** - * identity - EAP Identity - */ - 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. - */ - u8 *anonymous_identity; - - /** - * anonymous_identity_len - Length of anonymous_identity - */ - size_t anonymous_identity_len; - - /** - * eappsk - EAP-PSK/PAX/SAKE pre-shared key - */ - u8 *eappsk; - - /** - * eappsk_len - EAP-PSK/PAX/SAKE pre-shared key length - * - * This field is always 16 for the current version of EAP-PSK/PAX and - * 32 for EAP-SAKE. - */ - size_t eappsk_len; - - /** - * nai - User NAI (for EAP-PSK/PAX/SAKE) - */ - u8 *nai; - - /** - * nai_len - Length of nai field - */ - size_t nai_len; - - /** - * password - Password string for EAP - */ - 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>. - * - * 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). - * - * fast_provisioning=1 can be used to enable in-line provisioning of - * EAP-FAST credentials (PAC) - */ - 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; - - /** - * 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; - -#define EAPOL_FLAG_REQUIRE_KEY_UNICAST BIT(0) -#define EAPOL_FLAG_REQUIRE_KEY_BROADCAST BIT(1) - /** - * eapol_flags - Bit field of IEEE 802.1X/EAPOL options (EAPOL_FLAG_*) - */ - int eapol_flags; - -#endif /* IEEE8021X_EAPOL */ - -#define NUM_WEP_KEYS 4 -#define MAX_WEP_KEY_LEN 16 - /** - * wep_key - WEP keys - */ - u8 wep_key[NUM_WEP_KEYS][MAX_WEP_KEY_LEN]; - - /** - * wep_key_len - WEP key lengths - */ - size_t wep_key_len[NUM_WEP_KEYS]; - - /** - * wep_tx_keyidx - Default key index for TX frames using WEP - */ - int wep_tx_keyidx; - - /** - * proactive_key_caching - Enable proactive key caching - * - * This field can be used to enable proactive key caching which is also - * known as opportunistic PMKSA caching for WPA2. This is disabled (0) - * by default. Enable by setting this to 1. - * - * Proactive key caching is used to make supplicant assume that the APs - * are using the same PMK and generate PMKSA cache entries without - * doing RSN pre-authentication. This requires support from the AP side - * and is normally used with wireless switches that co-locate the - * authenticator. - */ - int proactive_key_caching; - - /** - * mixed_cell - Whether mixed cells are allowed - * - * This option can be used to configure whether so called mixed cells, - * i.e., networks that use both plaintext and encryption in the same - * SSID, are allowed. This is disabled (0) by default. Enable by - * setting this to 1. - */ - int mixed_cell; - -#ifdef IEEE8021X_EAPOL - - /** - * 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; - - /** - * leap - Number of EAP methods using LEAP - * - * This field should be set to 1 if LEAP is enabled. This is used to - * select IEEE 802.11 authentication algorithm. - */ - int leap; - - /** - * non_leap - Number of EAP methods not using LEAP - * - * This field should be set to >0 if any EAP method other than LEAP is - * enabled. This is used to select IEEE 802.11 authentication - * algorithm. - */ - int non_leap; - - /** - * eap_workaround - EAP workarounds enabled - * - * wpa_supplicant supports number of "EAP workarounds" to work around - * interoperability issues with incorrectly behaving authentication - * servers. This is recommended to be enabled by default because some - * of the issues are present in large number of authentication servers. - * - * Strict EAP conformance mode can be configured by disabling - * workarounds with eap_workaround = 0. - */ - unsigned int eap_workaround; - - /** - * 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; - -#endif /* IEEE8021X_EAPOL */ - - /** - * mode - IEEE 802.11 operation mode (Infrastucture/IBSS) - * - * 0 = infrastructure (Managed) mode, i.e., associate with an AP. - * - * 1 = IBSS (ad-hoc, peer-to-peer) - * - * Note: IBSS can only be used with key_mgmt NONE (plaintext and - * static WEP) and key_mgmt=WPA-NONE (fixed group key TKIP/CCMP). In - * addition, ap_scan has to be set to 2 for IBSS. WPA-None requires - * following network block options: proto=WPA, key_mgmt=WPA-NONE, - * pairwise=NONE, group=TKIP (or CCMP, but not both), and psk must also - * be set (either directly or using ASCII passphrase). - */ - int mode; - -#ifdef IEEE8021X_EAPOL - - /** - * 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; - -#endif /* IEEE8021X_EAPOL */ - - /** - * disabled - Whether this network is currently disabled - * - * 0 = this network can be used (default). - * 1 = this network block is disabled (can be enabled through - * ctrl_iface, e.g., with wpa_cli or wpa_gui). - */ - int disabled; - - /** - * peerkey - Whether PeerKey handshake for direct links is allowed - * - * This is only used when both RSN/WPA2 and IEEE 802.11e (QoS) are - * enabled. - * - * 0 = disabled (default) - * 1 = enabled - */ - int peerkey; - -#ifdef IEEE8021X_EAPOL - - /** - * 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; - -#endif /* IEEE8021X_EAPOL */ - - /** - * id_str - Network identifier string for external scripts - * - * This value is passed to external ctrl_iface monitors in - * WPA_EVENT_CONNECTED event and wpa_cli sets this as WPA_ID_STR - * environment variable for action scripts. - */ - char *id_str; - -#ifdef CONFIG_IEEE80211W - /** - * ieee80211w - Whether management frame protection is enabled - * - * This value is used to configure policy for management frame - * protection (IEEE 802.11w). 0 = disabled, 1 = optional, 2 = required. - */ - enum { - NO_IEEE80211W = 0, - IEEE80211W_OPTIONAL = 1, - IEEE80211W_REQUIRED = 2 - } ieee80211w; -#endif /* CONFIG_IEEE80211W */ - - /** - * frequency - Channel frequency in megahertz (MHz) for IBSS - * - * This value is used to configure the initial channel for IBSS (adhoc) - * networks, e.g., 2412 = IEEE 802.11b/g channel 1. It is ignored in - * the infrastructure mode. In addition, this value is only used by the - * station that creates the IBSS. If an IBSS network with the - * configured SSID is already present, the frequency of the network - * will be used instead of this configured value. - */ - int frequency; -}; - -int wpa_config_allowed_eap_method(struct wpa_ssid *ssid, int vendor, - u32 method); - -#endif /* CONFIG_SSID_H */ diff --git a/contrib/wpa_supplicant/config_types.h b/contrib/wpa_supplicant/config_types.h deleted file mode 100644 index ffcffa3c0cd4..000000000000 --- a/contrib/wpa_supplicant/config_types.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * hostapd / Shared configuration file defines - * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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_TYPES_H -#define CONFIG_TYPES_H - -struct hostapd_ip_addr { - union { - struct in_addr v4; -#ifdef CONFIG_IPV6 - struct in6_addr v6; -#endif /* CONFIG_IPV6 */ - } u; - int af; /* AF_INET / AF_INET6 */ -}; - -#endif /* CONFIG_TYPES_H */ diff --git a/contrib/wpa_supplicant/crypto.c b/contrib/wpa_supplicant/crypto.c deleted file mode 100644 index c5edd24c4b55..000000000000 --- a/contrib/wpa_supplicant/crypto.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - * WPA Supplicant / wrapper functions for libcrypto - * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 <openssl/opensslv.h> -#include <openssl/md4.h> -#include <openssl/md5.h> -#include <openssl/sha.h> -#include <openssl/des.h> -#include <openssl/aes.h> - -#include "common.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 */ - - -void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - MD4_CTX ctx; - size_t i; - - MD4_Init(&ctx); - for (i = 0; i < num_elem; i++) - MD4_Update(&ctx, addr[i], len[i]); - MD4_Final(mac, &ctx); -} - - -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); -} - - -#ifdef EAP_TLS_FUNCS -void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - MD5_CTX ctx; - size_t i; - - MD5_Init(&ctx); - for (i = 0; i < num_elem; i++) - MD5_Update(&ctx, addr[i], len[i]); - MD5_Final(mac, &ctx); -} - - -void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - SHA_CTX ctx; - size_t i; - - SHA1_Init(&ctx); - for (i = 0; i < num_elem; i++) - SHA1_Update(&ctx, addr[i], len[i]); - SHA1_Final(mac, &ctx); -} - - -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; -} - - -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); -} -#endif /* EAP_TLS_FUNCS */ diff --git a/contrib/wpa_supplicant/crypto.h b/contrib/wpa_supplicant/crypto.h deleted file mode 100644 index 00b13b91c48e..000000000000 --- a/contrib/wpa_supplicant/crypto.h +++ /dev/null @@ -1,413 +0,0 @@ -/* - * WPA Supplicant / wrapper functions for crypto libraries - * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 - */ -void 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 - */ -void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); - -/** - * 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 - */ -void 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 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 - */ -void 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 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 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 - * 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); - -/** - * 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 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_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 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 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 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 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); - -#endif /* CRYPTO_H */ diff --git a/contrib/wpa_supplicant/crypto_cryptoapi.c b/contrib/wpa_supplicant/crypto_cryptoapi.c deleted file mode 100644 index bb0573078d24..000000000000 --- a/contrib/wpa_supplicant/crypto_cryptoapi.c +++ /dev/null @@ -1,801 +0,0 @@ -/* - * WPA Supplicant / Crypto wrapper for Microsoft CryptoAPI - * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 <windows.h> -#include <wincrypt.h> - -#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 CONFIG_TLS_INTERNAL -#ifdef __MINGW32_VERSION -/* - * MinGW does not yet include all the needed definitions for CryptoAPI, so - * define here whatever extra is needed. - */ - -static PCCERT_CONTEXT WINAPI -(*CertCreateCertificateContext)(DWORD dwCertEncodingType, - const BYTE *pbCertEncoded, - DWORD cbCertEncoded) -= NULL; /* to be loaded from crypt32.dll */ - -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 (CertCreateCertificateContext) - return 0; - - dll = LoadLibrary("crypt32"); - if (dll == NULL) { - wpa_printf(MSG_DEBUG, "CryptoAPI: Could not load crypt32 " - "library"); - return -1; - } - - CertCreateCertificateContext = (void *) GetProcAddress( - dll, "CertCreateCertificateContext"); - if (CertCreateCertificateContext == NULL) { - wpa_printf(MSG_DEBUG, "CryptoAPI: Could not get " - "CertCreateCertificateContext() address from " - "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 */ -#endif /* CONFIG_TLS_INTERNAL */ - - -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; -} - - -void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - 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); -} - - -#ifdef EAP_TLS_FUNCS -void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - cryptoapi_hash_vector(CALG_MD5, 16, num_elem, addr, len, mac); -} - - -void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - 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); -} - -#ifdef CONFIG_TLS_INTERNAL - -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) -{ - /* 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) -{ -} - -#endif /* CONFIG_TLS_INTERNAL */ - -#endif /* EAP_TLS_FUNCS */ diff --git a/contrib/wpa_supplicant/crypto_gnutls.c b/contrib/wpa_supplicant/crypto_gnutls.c deleted file mode 100644 index 4bf75f132a00..000000000000 --- a/contrib/wpa_supplicant/crypto_gnutls.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * WPA Supplicant / wrapper functions for libgcrypt - * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 <gcrypt.h> - -#include "common.h" -#include "crypto.h" - -void 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; - 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); -} - - -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); -} - - -#ifdef EAP_TLS_FUNCS -void 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; - 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); -} - - -void 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; - 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); -} - - -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; -} - - -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); -} -#endif /* EAP_TLS_FUNCS */ diff --git a/contrib/wpa_supplicant/crypto_internal.c b/contrib/wpa_supplicant/crypto_internal.c deleted file mode 100644 index d0c20371a73d..000000000000 --- a/contrib/wpa_supplicant/crypto_internal.c +++ /dev/null @@ -1,670 +0,0 @@ -/* - * WPA Supplicant / Crypto wrapper for internal crypto implementation - * Copyright (c) 2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "md5.h" -#include "sha1.h" -#include "rc4.h" -#include "aes.h" -#include "rsa.h" -#include "bignum.h" - - -#ifdef EAP_TLS_FUNCS - -#ifdef CONFIG_TLS_INTERNAL - -/* 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); - - -struct MD5Context { - u32 buf[4]; - u32 bits[2]; - u8 in[64]; -}; - -struct SHA1Context { - u32 state[5]; - u32 count[2]; - unsigned char buffer[64]; -}; - - -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; -} - - -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; - } 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; - 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; - 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; - 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); -} - - -/* 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) -{ - 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; -} - - -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, 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 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, (struct crypto_rsa_key *) key, - 0, 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, (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) -{ - size_t len; - u8 *pos; - - len = *plain_len; - if (crypto_rsa_exptmod(crypt, crypt_len, plain, &len, - (struct crypto_rsa_key *) key, 0) < 0) - 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) -{ - return 0; -} - - -void crypto_global_deinit(void) -{ -} - - -#ifdef EAP_FAST - -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 = 0; - - 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; -} - -#endif /* EAP_FAST */ - - -#endif /* CONFIG_TLS_INTERNAL */ - -#endif /* EAP_TLS_FUNCS */ diff --git a/contrib/wpa_supplicant/crypto_libtomcrypt.c b/contrib/wpa_supplicant/crypto_libtomcrypt.c deleted file mode 100644 index e82097f10a00..000000000000 --- a/contrib/wpa_supplicant/crypto_libtomcrypt.c +++ /dev/null @@ -1,736 +0,0 @@ -/* - * WPA Supplicant / Crypto wrapper for LibTomCrypt (for internal TLSv1) - * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 <tomcrypt.h> - -#include "common.h" -#include "rc4.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 - - -void 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); -} - - -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); -} - - -#ifdef EAP_TLS_FUNCS -void 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); -} - - -void 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); -} - - -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); -} - - -#ifdef CONFIG_TLS_INTERNAL - -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) -{ - 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 EAP_FAST - -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 /* EAP_FAST */ - -#endif /* CONFIG_TLS_INTERNAL */ - -#endif /* EAP_TLS_FUNCS */ diff --git a/contrib/wpa_supplicant/crypto_none.c b/contrib/wpa_supplicant/crypto_none.c deleted file mode 100644 index f18c2a8ded95..000000000000 --- a/contrib/wpa_supplicant/crypto_none.c +++ /dev/null @@ -1,28 +0,0 @@ -/* - * WPA Supplicant / Empty template functions for crypto wrapper - * Copyright (c) 2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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" - - -void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ -} - - -void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) -{ -} diff --git a/contrib/wpa_supplicant/ctrl_iface.c b/contrib/wpa_supplicant/ctrl_iface.c deleted file mode 100644 index 52d5bd90732c..000000000000 --- a/contrib/wpa_supplicant/ctrl_iface.c +++ /dev/null @@ -1,1380 +0,0 @@ -/* - * WPA Supplicant / Control interface (shared code for all backends) - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "wpa.h" -#include "wpa_supplicant.h" -#include "config.h" -#include "eapol_sm.h" -#include "wpa_supplicant_i.h" -#include "ctrl_iface.h" -#include "l2_packet.h" -#include "preauth.h" -#include "pmksa_cache.h" -#include "wpa_ctrl.h" -#include "eap.h" - - -static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global, - char *buf, int len); - - -static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, - 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 (os_strcasecmp(cmd, "EAPOL::heldPeriod") == 0) { - eapol_sm_configure(wpa_s->eapol, - atoi(value), -1, -1, -1); - } else if (os_strcasecmp(cmd, "EAPOL::authPeriod") == 0) { - eapol_sm_configure(wpa_s->eapol, - -1, atoi(value), -1, -1); - } else if (os_strcasecmp(cmd, "EAPOL::startPeriod") == 0) { - eapol_sm_configure(wpa_s->eapol, - -1, -1, atoi(value), -1); - } else if (os_strcasecmp(cmd, "EAPOL::maxStart") == 0) { - eapol_sm_configure(wpa_s->eapol, - -1, -1, -1, atoi(value)); - } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) { - if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, - atoi(value))) - ret = -1; - } else if (os_strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") == - 0) { - if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, - atoi(value))) - ret = -1; - } else if (os_strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) { - if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value))) - ret = -1; - } else - ret = -1; - - return ret; -} - - -#ifdef IEEE8021X_EAPOL -static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s, - char *addr) -{ - u8 bssid[ETH_ALEN]; - - if (hwaddr_aton(addr, bssid)) { - wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address " - "'%s'", addr); - return -1; - } - - wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid)); - rsn_preauth_deinit(wpa_s->wpa); - if (rsn_preauth_init(wpa_s->wpa, bssid, wpa_s->current_ssid)) - return -1; - - return 0; -} -#endif /* IEEE8021X_EAPOL */ - - -#ifdef CONFIG_PEERKEY -/* MLME-STKSTART.request(peer) */ -static int wpa_supplicant_ctrl_iface_stkstart( - struct wpa_supplicant *wpa_s, char *addr) -{ - u8 peer[ETH_ALEN]; - - if (hwaddr_aton(addr, peer)) { - wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid " - "address '%s'", peer); - return -1; - } - - wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR, - MAC2STR(peer)); - - return wpa_sm_stkstart(wpa_s->wpa, peer); -} -#endif /* CONFIG_PEERKEY */ - - -static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s, - char *rsp) -{ -#ifdef IEEE8021X_EAPOL - char *pos, *id_pos; - int id; - struct wpa_ssid *ssid; - - pos = os_strchr(rsp, '-'); - if (pos == NULL) - return -1; - *pos++ = '\0'; - id_pos = pos; - pos = os_strchr(pos, ':'); - if (pos == NULL) - return -1; - *pos++ = '\0'; - id = atoi(id_pos); - wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id); - wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", - (u8 *) pos, os_strlen(pos)); - - ssid = wpa_config_get_network(wpa_s->conf, id); - if (ssid == NULL) { - wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " - "to update", id); - return -1; - } - - if (os_strcmp(rsp, "IDENTITY") == 0) { - os_free(ssid->identity); - ssid->identity = (u8 *) os_strdup(pos); - ssid->identity_len = os_strlen(pos); - ssid->pending_req_identity = 0; - if (ssid == wpa_s->current_ssid) - wpa_s->reassociate = 1; - } else if (os_strcmp(rsp, "PASSWORD") == 0) { - os_free(ssid->password); - ssid->password = (u8 *) os_strdup(pos); - ssid->password_len = os_strlen(pos); - ssid->pending_req_password = 0; - if (ssid == wpa_s->current_ssid) - wpa_s->reassociate = 1; - } else if (os_strcmp(rsp, "NEW_PASSWORD") == 0) { - os_free(ssid->new_password); - ssid->new_password = (u8 *) os_strdup(pos); - ssid->new_password_len = os_strlen(pos); - ssid->pending_req_new_password = 0; - if (ssid == wpa_s->current_ssid) - wpa_s->reassociate = 1; - } else if (os_strcmp(rsp, "PIN") == 0) { - os_free(ssid->pin); - ssid->pin = os_strdup(pos); - ssid->pending_req_pin = 0; - if (ssid == wpa_s->current_ssid) - wpa_s->reassociate = 1; - } else if (os_strcmp(rsp, "OTP") == 0) { - os_free(ssid->otp); - ssid->otp = (u8 *) os_strdup(pos); - ssid->otp_len = os_strlen(pos); - os_free(ssid->pending_req_otp); - ssid->pending_req_otp = NULL; - ssid->pending_req_otp_len = 0; - } else if (os_strcmp(rsp, "PASSPHRASE") == 0) { - os_free(ssid->private_key_passwd); - ssid->private_key_passwd = (u8 *) os_strdup(pos); - ssid->pending_req_passphrase = 0; - if (ssid == wpa_s->current_ssid) - wpa_s->reassociate = 1; - } else { - wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", rsp); - return -1; - } - - return 0; -#else /* IEEE8021X_EAPOL */ - wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included"); - return -1; -#endif /* IEEE8021X_EAPOL */ -} - - -static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s, - const char *params, - char *buf, size_t buflen) -{ - char *pos, *end, tmp[30]; - int res, verbose, ret; - - verbose = os_strcmp(params, "-VERBOSE") == 0; - pos = buf; - end = buf + buflen; - if (wpa_s->wpa_state >= WPA_ASSOCIATED) { - struct wpa_ssid *ssid = wpa_s->current_ssid; - ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n", - MAC2STR(wpa_s->bssid)); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - if (ssid) { - u8 *_ssid = ssid->ssid; - size_t ssid_len = ssid->ssid_len; - u8 ssid_buf[MAX_SSID_LEN]; - if (ssid_len == 0) { - int _res = wpa_drv_get_ssid(wpa_s, ssid_buf); - if (_res < 0) - ssid_len = 0; - else - ssid_len = _res; - _ssid = ssid_buf; - } - ret = os_snprintf(pos, end - pos, "ssid=%s\nid=%d\n", - wpa_ssid_txt(_ssid, ssid_len), - ssid->id); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - - if (ssid->id_str) { - ret = os_snprintf(pos, end - pos, - "id_str=%s\n", - ssid->id_str); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - } - } - - pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose); - } - ret = os_snprintf(pos, end - pos, "wpa_state=%s\n", - wpa_supplicant_state_txt(wpa_s->wpa_state)); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - - if (wpa_s->l2 && - l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) { - ret = os_snprintf(pos, end - pos, "ip_address=%s\n", tmp); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - } - - if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X || - wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { - res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos, - verbose); - if (res >= 0) - pos += res; - } - - res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose); - if (res >= 0) - pos += res; - - return pos - buf; -} - - -static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s, - char *cmd) -{ - char *pos; - int id; - struct wpa_ssid *ssid; - u8 bssid[ETH_ALEN]; - - /* cmd: "<network id> <BSSID>" */ - pos = os_strchr(cmd, ' '); - if (pos == NULL) - return -1; - *pos++ = '\0'; - id = atoi(cmd); - wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos); - if (hwaddr_aton(pos, bssid)) { - wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos); - return -1; - } - - ssid = wpa_config_get_network(wpa_s->conf, id); - if (ssid == NULL) { - wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d " - "to update", id); - return -1; - } - - os_memcpy(ssid->bssid, bssid, ETH_ALEN); - ssid->bssid_set = - os_memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) != 0; - - - return 0; -} - - -static int wpa_supplicant_ctrl_iface_list_networks( - struct wpa_supplicant *wpa_s, char *buf, size_t buflen) -{ - char *pos, *end; - struct wpa_ssid *ssid; - int ret; - - pos = buf; - end = buf + buflen; - ret = os_snprintf(pos, end - pos, - "network id / ssid / bssid / flags\n"); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - - ssid = wpa_s->conf->ssid; - while (ssid) { - ret = os_snprintf(pos, end - pos, "%d\t%s", - ssid->id, - wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - if (ssid->bssid_set) { - ret = os_snprintf(pos, end - pos, "\t" MACSTR, - MAC2STR(ssid->bssid)); - } else { - ret = os_snprintf(pos, end - pos, "\tany"); - } - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - ret = os_snprintf(pos, end - pos, "\t%s%s", - ssid == wpa_s->current_ssid ? - "[CURRENT]" : "", - ssid->disabled ? "[DISABLED]" : ""); - 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; - - ssid = ssid->next; - } - - return pos - buf; -} - - -static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher) -{ - int first = 1, ret; - ret = os_snprintf(pos, end - pos, "-"); - if (ret < 0 || ret >= end - pos) - return pos; - pos += ret; - if (cipher & WPA_CIPHER_NONE) { - ret = os_snprintf(pos, end - pos, "%sNONE", first ? "" : "+"); - if (ret < 0 || ret >= end - pos) - return pos; - pos += ret; - first = 0; - } - if (cipher & WPA_CIPHER_WEP40) { - ret = os_snprintf(pos, end - pos, "%sWEP40", first ? "" : "+"); - if (ret < 0 || ret >= end - pos) - return pos; - pos += ret; - first = 0; - } - if (cipher & WPA_CIPHER_WEP104) { - ret = os_snprintf(pos, end - pos, "%sWEP104", - first ? "" : "+"); - if (ret < 0 || ret >= end - pos) - return pos; - pos += ret; - first = 0; - } - if (cipher & WPA_CIPHER_TKIP) { - ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : "+"); - if (ret < 0 || ret >= end - pos) - return pos; - pos += ret; - first = 0; - } - if (cipher & WPA_CIPHER_CCMP) { - ret = os_snprintf(pos, end - pos, "%sCCMP", first ? "" : "+"); - if (ret < 0 || ret >= end - pos) - return pos; - pos += ret; - first = 0; - } - return pos; -} - - -static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto, - const u8 *ie, size_t ie_len) -{ - struct wpa_ie_data data; - int first, ret; - - ret = os_snprintf(pos, end - pos, "[%s-", proto); - if (ret < 0 || ret >= end - pos) - return pos; - pos += ret; - - if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) { - ret = os_snprintf(pos, end - pos, "?]"); - if (ret < 0 || ret >= end - pos) - return pos; - pos += ret; - return pos; - } - - first = 1; - if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) { - ret = os_snprintf(pos, end - pos, "%sEAP", first ? "" : "+"); - if (ret < 0 || ret >= end - pos) - return pos; - pos += ret; - first = 0; - } - if (data.key_mgmt & WPA_KEY_MGMT_PSK) { - ret = os_snprintf(pos, end - pos, "%sPSK", first ? "" : "+"); - if (ret < 0 || ret >= end - pos) - return pos; - pos += ret; - first = 0; - } - if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) { - ret = os_snprintf(pos, end - pos, "%sNone", first ? "" : "+"); - if (ret < 0 || ret >= end - pos) - return pos; - pos += ret; - first = 0; - } - - pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher); - - if (data.capabilities & WPA_CAPABILITY_PREAUTH) { - ret = os_snprintf(pos, end - pos, "-preauth"); - if (ret < 0 || ret >= end - pos) - return pos; - pos += ret; - } - - ret = os_snprintf(pos, end - pos, "]"); - if (ret < 0 || ret >= end - pos) - return pos; - pos += ret; - - return pos; -} - - -static int wpa_supplicant_ctrl_iface_scan_results( - struct wpa_supplicant *wpa_s, char *buf, size_t buflen) -{ - char *pos, *end; - struct wpa_scan_result *res; - int i, ret; - - if (wpa_s->scan_results == NULL && - wpa_supplicant_get_scan_results(wpa_s) < 0) - return 0; - if (wpa_s->scan_results == NULL) - return 0; - - pos = buf; - end = buf + buflen; - ret = os_snprintf(pos, end - pos, "bssid / frequency / signal level / " - "flags / ssid\n"); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - - for (i = 0; i < wpa_s->num_scan_results; i++) { - res = &wpa_s->scan_results[i]; - ret = os_snprintf(pos, end - pos, MACSTR "\t%d\t%d\t", - MAC2STR(res->bssid), res->freq, res->level); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - if (res->wpa_ie_len) { - pos = wpa_supplicant_ie_txt(pos, end, "WPA", - res->wpa_ie, - res->wpa_ie_len); - } - if (res->rsn_ie_len) { - pos = wpa_supplicant_ie_txt(pos, end, "WPA2", - res->rsn_ie, - res->rsn_ie_len); - } - if (!res->wpa_ie_len && !res->rsn_ie_len && - res->caps & IEEE80211_CAP_PRIVACY) { - ret = os_snprintf(pos, end - pos, "[WEP]"); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - } - if (res->caps & IEEE80211_CAP_IBSS) { - ret = os_snprintf(pos, end - pos, "[IBSS]"); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - } - - ret = os_snprintf(pos, end - pos, "\t%s", - wpa_ssid_txt(res->ssid, res->ssid_len)); - 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 wpa_supplicant_ctrl_iface_select_network( - struct wpa_supplicant *wpa_s, char *cmd) -{ - int id; - struct wpa_ssid *ssid; - - /* cmd: "<network id>" or "any" */ - if (os_strcmp(cmd, "any") == 0) { - wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any"); - ssid = wpa_s->conf->ssid; - while (ssid) { - ssid->disabled = 0; - ssid = ssid->next; - } - wpa_s->reassociate = 1; - wpa_supplicant_req_scan(wpa_s, 0, 0); - return 0; - } - - id = atoi(cmd); - wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id); - - ssid = wpa_config_get_network(wpa_s->conf, id); - if (ssid == NULL) { - wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " - "id=%d", id); - return -1; - } - - if (ssid != wpa_s->current_ssid && wpa_s->current_ssid) - wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING); - - /* Mark all other networks disabled and trigger reassociation */ - ssid = wpa_s->conf->ssid; - while (ssid) { - ssid->disabled = id != ssid->id; - ssid = ssid->next; - } - wpa_s->reassociate = 1; - wpa_supplicant_req_scan(wpa_s, 0, 0); - - return 0; -} - - -static int wpa_supplicant_ctrl_iface_enable_network( - struct wpa_supplicant *wpa_s, char *cmd) -{ - int id; - struct wpa_ssid *ssid; - - /* cmd: "<network id>" */ - id = atoi(cmd); - wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id); - - ssid = wpa_config_get_network(wpa_s->conf, id); - if (ssid == NULL) { - wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " - "id=%d", id); - return -1; - } - - if (wpa_s->current_ssid == NULL && ssid->disabled) { - /* - * Try to reassociate since there is no current configuration - * and a new network was made available. */ - wpa_s->reassociate = 1; - wpa_supplicant_req_scan(wpa_s, 0, 0); - } - ssid->disabled = 0; - - return 0; -} - - -static int wpa_supplicant_ctrl_iface_disable_network( - struct wpa_supplicant *wpa_s, char *cmd) -{ - int id; - struct wpa_ssid *ssid; - - /* cmd: "<network id>" */ - id = atoi(cmd); - wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id); - - ssid = wpa_config_get_network(wpa_s->conf, id); - if (ssid == NULL) { - wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " - "id=%d", id); - return -1; - } - - if (ssid == wpa_s->current_ssid) - wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING); - ssid->disabled = 1; - - return 0; -} - - -static int wpa_supplicant_ctrl_iface_add_network( - struct wpa_supplicant *wpa_s, char *buf, size_t buflen) -{ - struct wpa_ssid *ssid; - int ret; - - wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK"); - - ssid = wpa_config_add_network(wpa_s->conf); - if (ssid == NULL) - return -1; - ssid->disabled = 1; - wpa_config_set_network_defaults(ssid); - - ret = os_snprintf(buf, buflen, "%d\n", ssid->id); - if (ret < 0 || (size_t) ret >= buflen) - return -1; - return ret; -} - - -static int wpa_supplicant_ctrl_iface_remove_network( - struct wpa_supplicant *wpa_s, char *cmd) -{ - int id; - struct wpa_ssid *ssid; - - /* cmd: "<network id>" */ - id = atoi(cmd); - wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id); - - ssid = wpa_config_get_network(wpa_s->conf, id); - if (ssid == NULL || - wpa_config_remove_network(wpa_s->conf, id) < 0) { - wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " - "id=%d", id); - return -1; - } - - if (ssid == wpa_s->current_ssid) { - /* - * Invalidate the EAP session cache if the current network is - * removed. - */ - eapol_sm_invalidate_cached_session(wpa_s->eapol); - - wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING); - } - - return 0; -} - - -static int wpa_supplicant_ctrl_iface_set_network( - struct wpa_supplicant *wpa_s, char *cmd) -{ - int id; - struct wpa_ssid *ssid; - char *name, *value; - - /* cmd: "<network id> <variable name> <value>" */ - name = os_strchr(cmd, ' '); - if (name == NULL) - return -1; - *name++ = '\0'; - - value = os_strchr(name, ' '); - if (value == NULL) - return -1; - *value++ = '\0'; - - id = atoi(cmd); - wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'", - id, name); - wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value", - (u8 *) value, os_strlen(value)); - - ssid = wpa_config_get_network(wpa_s->conf, id); - if (ssid == NULL) { - wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " - "id=%d", id); - return -1; - } - - if (wpa_config_set(ssid, name, value, 0) < 0) { - wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network " - "variable '%s'", name); - return -1; - } - - if (wpa_s->current_ssid == ssid) { - /* - * Invalidate the EAP session cache if anything in the current - * configuration changes. - */ - eapol_sm_invalidate_cached_session(wpa_s->eapol); - } - - if ((os_strcmp(name, "psk") == 0 && - value[0] == '"' && ssid->ssid_len) || - (os_strcmp(name, "ssid") == 0 && ssid->passphrase)) - wpa_config_update_psk(ssid); - - return 0; -} - - -static int wpa_supplicant_ctrl_iface_get_network( - struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) -{ - int id; - struct wpa_ssid *ssid; - char *name, *value; - - /* cmd: "<network id> <variable name>" */ - name = os_strchr(cmd, ' '); - if (name == NULL || buflen == 0) - return -1; - *name++ = '\0'; - - id = atoi(cmd); - wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'", - id, name); - - ssid = wpa_config_get_network(wpa_s->conf, id); - if (ssid == NULL) { - wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network " - "id=%d", id); - return -1; - } - - value = wpa_config_get_no_key(ssid, name); - if (value == NULL) { - wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network " - "variable '%s'", name); - return -1; - } - - os_snprintf(buf, buflen, "%s", value); - buf[buflen - 1] = '\0'; - - os_free(value); - - return os_strlen(buf); -} - - -static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s) -{ - int ret; - - if (!wpa_s->conf->update_config) { - wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed " - "to update configuration (update_config=0)"); - return -1; - } - - ret = wpa_config_write(wpa_s->confname, wpa_s->conf); - if (ret) { - wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to " - "update configuration"); - } else { - wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration" - " updated"); - } - - return ret; -} - - -static int wpa_supplicant_ctrl_iface_get_capability( - struct wpa_supplicant *wpa_s, const char *_field, char *buf, - size_t buflen) -{ - struct wpa_driver_capa capa; - int res, first = 1, ret; - char *pos, *end, *strict; - char field[30]; - - /* Determine whether or not strict checking was requested */ - os_snprintf(field, sizeof(field), "%s", _field); - field[sizeof(field) - 1] = '\0'; - strict = os_strchr(field, ' '); - if (strict != NULL) { - *strict++ = '\0'; - if (os_strcmp(strict, "strict") != 0) - return -1; - } - - wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s", - field, strict ? strict : ""); - - if (os_strcmp(field, "eap") == 0) { - return eap_get_names(buf, buflen); - } - - res = wpa_drv_get_capa(wpa_s, &capa); - - pos = buf; - end = pos + buflen; - - if (os_strcmp(field, "pairwise") == 0) { - if (res < 0) { - if (strict) - return 0; - ret = os_snprintf(buf, buflen, "CCMP TKIP NONE"); - if (ret < 0 || (size_t) ret >= buflen) - return -1; - return ret; - } - - if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) { - ret = os_snprintf(pos, end - pos, "%sCCMP", - first ? "" : " "); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - first = 0; - } - - if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) { - ret = os_snprintf(pos, end - pos, "%sTKIP", - first ? "" : " "); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - first = 0; - } - - if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { - ret = os_snprintf(pos, end - pos, "%sNONE", - first ? "" : " "); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - first = 0; - } - - return pos - buf; - } - - if (os_strcmp(field, "group") == 0) { - if (res < 0) { - if (strict) - return 0; - ret = os_snprintf(buf, buflen, - "CCMP TKIP WEP104 WEP40"); - if (ret < 0 || (size_t) ret >= buflen) - return -1; - return ret; - } - - if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) { - ret = os_snprintf(pos, end - pos, "%sCCMP", - first ? "" : " "); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - first = 0; - } - - if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) { - ret = os_snprintf(pos, end - pos, "%sTKIP", - first ? "" : " "); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - first = 0; - } - - if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) { - ret = os_snprintf(pos, end - pos, "%sWEP104", - first ? "" : " "); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - first = 0; - } - - if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) { - ret = os_snprintf(pos, end - pos, "%sWEP40", - first ? "" : " "); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - first = 0; - } - - return pos - buf; - } - - if (os_strcmp(field, "key_mgmt") == 0) { - if (res < 0) { - if (strict) - return 0; - ret = os_snprintf(buf, buflen, "WPA-PSK WPA-EAP " - "IEEE8021X WPA-NONE NONE"); - if (ret < 0 || (size_t) ret >= buflen) - return -1; - return ret; - } - - ret = os_snprintf(pos, end - pos, "NONE IEEE8021X"); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - - if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) { - ret = os_snprintf(pos, end - pos, " WPA-EAP"); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - } - - if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { - ret = os_snprintf(pos, end - pos, " WPA-PSK"); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - } - - if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { - ret = os_snprintf(pos, end - pos, " WPA-NONE"); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - } - - return pos - buf; - } - - if (os_strcmp(field, "proto") == 0) { - if (res < 0) { - if (strict) - return 0; - ret = os_snprintf(buf, buflen, "RSN WPA"); - if (ret < 0 || (size_t) ret >= buflen) - return -1; - return ret; - } - - if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { - ret = os_snprintf(pos, end - pos, "%sRSN", - first ? "" : " "); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - first = 0; - } - - if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | - WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) { - ret = os_snprintf(pos, end - pos, "%sWPA", - first ? "" : " "); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - first = 0; - } - - return pos - buf; - } - - if (os_strcmp(field, "auth_alg") == 0) { - if (res < 0) { - if (strict) - return 0; - ret = os_snprintf(buf, buflen, "OPEN SHARED LEAP"); - if (ret < 0 || (size_t) ret >= buflen) - return -1; - return ret; - } - - if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) { - ret = os_snprintf(pos, end - pos, "%sOPEN", - first ? "" : " "); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - first = 0; - } - - if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) { - ret = os_snprintf(pos, end - pos, "%sSHARED", - first ? "" : " "); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - first = 0; - } - - if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) { - ret = os_snprintf(pos, end - pos, "%sLEAP", - first ? "" : " "); - if (ret < 0 || ret >= end - pos) - return pos - buf; - pos += ret; - first = 0; - } - - return pos - buf; - } - - wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'", - field); - - return -1; -} - - -static int wpa_supplicant_ctrl_iface_ap_scan( - struct wpa_supplicant *wpa_s, char *cmd) -{ - int ap_scan = atoi(cmd); - - if (ap_scan < 0 || ap_scan > 2) - return -1; - wpa_s->conf->ap_scan = ap_scan; - return 0; -} - - -char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, - char *buf, size_t *resp_len) -{ - char *reply; - const int reply_size = 2048; - int ctrl_rsp = 0; - int reply_len; - - if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0 || - os_strncmp(buf, "SET_NETWORK ", 12) == 0) { - wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface", - (const u8 *) buf, os_strlen(buf)); - } else { - wpa_hexdump_ascii(MSG_DEBUG, "RX ctrl_iface", - (const u8 *) buf, os_strlen(buf)); - } - - reply = os_malloc(reply_size); - if (reply == NULL) { - *resp_len = 1; - return NULL; - } - - 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_strcmp(buf, "MIB") == 0) { - reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size); - if (reply_len >= 0) { - int res; - res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len, - reply_size - reply_len); - if (res < 0) - reply_len = -1; - else - reply_len += res; - } - } else if (os_strncmp(buf, "STATUS", 6) == 0) { - reply_len = wpa_supplicant_ctrl_iface_status( - wpa_s, buf + 6, reply, reply_size); - } else if (os_strcmp(buf, "PMKSA") == 0) { - reply_len = pmksa_cache_list(wpa_s->wpa, reply, reply_size); - } else if (os_strncmp(buf, "SET ", 4) == 0) { - if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4)) - reply_len = -1; - } else if (os_strcmp(buf, "LOGON") == 0) { - eapol_sm_notify_logoff(wpa_s->eapol, FALSE); - } else if (os_strcmp(buf, "LOGOFF") == 0) { - eapol_sm_notify_logoff(wpa_s->eapol, TRUE); - } else if (os_strcmp(buf, "REASSOCIATE") == 0) { - wpa_s->disconnected = 0; - wpa_s->reassociate = 1; - wpa_supplicant_req_scan(wpa_s, 0, 0); - } else if (os_strcmp(buf, "RECONNECT") == 0) { - if (wpa_s->disconnected) { - wpa_s->disconnected = 0; - wpa_s->reassociate = 1; - wpa_supplicant_req_scan(wpa_s, 0, 0); - } -#ifdef IEEE8021X_EAPOL - } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) { - if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8)) - reply_len = -1; -#endif /* IEEE8021X_EAPOL */ -#ifdef CONFIG_PEERKEY - } else if (os_strncmp(buf, "STKSTART ", 9) == 0) { - if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9)) - reply_len = -1; -#endif /* CONFIG_PEERKEY */ - } else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0) - { - if (wpa_supplicant_ctrl_iface_ctrl_rsp( - wpa_s, buf + os_strlen(WPA_CTRL_RSP))) - reply_len = -1; - else - ctrl_rsp = 1; - } else if (os_strcmp(buf, "RECONFIGURE") == 0) { - if (wpa_supplicant_reload_configuration(wpa_s)) - reply_len = -1; - } else if (os_strcmp(buf, "TERMINATE") == 0) { - eloop_terminate(); - } else if (os_strncmp(buf, "BSSID ", 6) == 0) { - if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6)) - reply_len = -1; - } else if (os_strcmp(buf, "LIST_NETWORKS") == 0) { - reply_len = wpa_supplicant_ctrl_iface_list_networks( - wpa_s, reply, reply_size); - } else if (os_strcmp(buf, "DISCONNECT") == 0) { - wpa_s->reassociate = 0; - wpa_s->disconnected = 1; - wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING); - } else if (os_strcmp(buf, "SCAN") == 0) { - wpa_s->scan_req = 2; - wpa_supplicant_req_scan(wpa_s, 0, 0); - } else if (os_strcmp(buf, "SCAN_RESULTS") == 0) { - reply_len = wpa_supplicant_ctrl_iface_scan_results( - wpa_s, reply, reply_size); - } else if (os_strncmp(buf, "SELECT_NETWORK ", 15) == 0) { - if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15)) - reply_len = -1; - } else if (os_strncmp(buf, "ENABLE_NETWORK ", 15) == 0) { - if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15)) - reply_len = -1; - } else if (os_strncmp(buf, "DISABLE_NETWORK ", 16) == 0) { - if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16)) - reply_len = -1; - } else if (os_strcmp(buf, "ADD_NETWORK") == 0) { - reply_len = wpa_supplicant_ctrl_iface_add_network( - wpa_s, reply, reply_size); - } else if (os_strncmp(buf, "REMOVE_NETWORK ", 15) == 0) { - if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15)) - reply_len = -1; - } else if (os_strncmp(buf, "SET_NETWORK ", 12) == 0) { - if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12)) - reply_len = -1; - } else if (os_strncmp(buf, "GET_NETWORK ", 12) == 0) { - reply_len = wpa_supplicant_ctrl_iface_get_network( - wpa_s, buf + 12, reply, reply_size); - } else if (os_strcmp(buf, "SAVE_CONFIG") == 0) { - if (wpa_supplicant_ctrl_iface_save_config(wpa_s)) - reply_len = -1; - } else if (os_strncmp(buf, "GET_CAPABILITY ", 15) == 0) { - reply_len = wpa_supplicant_ctrl_iface_get_capability( - wpa_s, buf + 15, reply, reply_size); - } else if (os_strncmp(buf, "AP_SCAN ", 8) == 0) { - if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8)) - reply_len = -1; - } else if (os_strcmp(buf, "INTERFACES") == 0) { - reply_len = wpa_supplicant_global_iface_interfaces( - wpa_s->global, 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; - } - - if (ctrl_rsp) - eapol_sm_notify_ctrl_response(wpa_s->eapol); - - *resp_len = reply_len; - return reply; -} - - -static int wpa_supplicant_global_iface_add(struct wpa_global *global, - char *cmd) -{ - struct wpa_interface iface; - char *pos; - - /* - * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param> - * TAB<bridge_ifname> - */ - wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd); - - os_memset(&iface, 0, sizeof(iface)); - - do { - iface.ifname = pos = cmd; - pos = os_strchr(pos, '\t'); - if (pos) - *pos++ = '\0'; - if (iface.ifname[0] == '\0') - return -1; - if (pos == NULL) - break; - - iface.confname = pos; - pos = os_strchr(pos, '\t'); - if (pos) - *pos++ = '\0'; - if (iface.confname[0] == '\0') - iface.confname = NULL; - if (pos == NULL) - break; - - iface.driver = pos; - pos = os_strchr(pos, '\t'); - if (pos) - *pos++ = '\0'; - if (iface.driver[0] == '\0') - iface.driver = NULL; - if (pos == NULL) - break; - - iface.ctrl_interface = pos; - pos = os_strchr(pos, '\t'); - if (pos) - *pos++ = '\0'; - if (iface.ctrl_interface[0] == '\0') - iface.ctrl_interface = NULL; - if (pos == NULL) - break; - - iface.driver_param = pos; - pos = os_strchr(pos, '\t'); - if (pos) - *pos++ = '\0'; - if (iface.driver_param[0] == '\0') - iface.driver_param = NULL; - if (pos == NULL) - break; - - iface.bridge_ifname = pos; - pos = os_strchr(pos, '\t'); - if (pos) - *pos++ = '\0'; - if (iface.bridge_ifname[0] == '\0') - iface.bridge_ifname = NULL; - if (pos == NULL) - break; - } while (0); - - if (wpa_supplicant_get_iface(global, iface.ifname)) - return -1; - - return wpa_supplicant_add_iface(global, &iface) ? 0 : -1; -} - - -static int wpa_supplicant_global_iface_remove(struct wpa_global *global, - char *cmd) -{ - struct wpa_supplicant *wpa_s; - - wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd); - - wpa_s = wpa_supplicant_get_iface(global, cmd); - if (wpa_s == NULL) - return -1; - return wpa_supplicant_remove_iface(global, wpa_s); -} - - -static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global, - char *buf, int len) -{ - int res; - char *pos, *end; - struct wpa_supplicant *wpa_s; - - wpa_s = global->ifaces; - pos = buf; - end = buf + len; - - while (wpa_s) { - res = os_snprintf(pos, end - pos, "%s\n", wpa_s->ifname); - if (res < 0 || res >= end - pos) { - *pos = '\0'; - break; - } - pos += res; - wpa_s = wpa_s->next; - } - return pos - buf; -} - - -char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global, - char *buf, size_t *resp_len) -{ - char *reply; - const int reply_size = 2048; - int reply_len; - - wpa_hexdump_ascii(MSG_DEBUG, "RX global ctrl_iface", - (const u8 *) buf, os_strlen(buf)); - - reply = os_malloc(reply_size); - if (reply == NULL) { - *resp_len = 1; - return NULL; - } - - 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, "INTERFACE_ADD ", 14) == 0) { - if (wpa_supplicant_global_iface_add(global, buf + 14)) - reply_len = -1; - } else if (os_strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) { - if (wpa_supplicant_global_iface_remove(global, buf + 17)) - reply_len = -1; - } else if (os_strcmp(buf, "INTERFACES") == 0) { - reply_len = wpa_supplicant_global_iface_interfaces( - global, reply, reply_size); - } else if (os_strcmp(buf, "TERMINATE") == 0) { - eloop_terminate(); - } else { - os_memcpy(reply, "UNKNOWN COMMAND\n", 16); - reply_len = 16; - } - - if (reply_len < 0) { - os_memcpy(reply, "FAIL\n", 5); - reply_len = 5; - } - - *resp_len = reply_len; - return reply; -} diff --git a/contrib/wpa_supplicant/ctrl_iface.h b/contrib/wpa_supplicant/ctrl_iface.h deleted file mode 100644 index 051d99a67dc6..000000000000 --- a/contrib/wpa_supplicant/ctrl_iface.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * WPA Supplicant / UNIX domain socket -based control interface - * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 - -#ifdef CONFIG_CTRL_IFACE - -/* Shared functions from ctrl_iface.c; to be called by ctrl_iface backends */ - -/** - * wpa_supplicant_ctrl_iface_process - Process ctrl_iface command - * @wpa_s: Pointer to wpa_supplicant data - * @buf: Received command buffer (nul terminated string) - * @resp_len: Variable to be set to the response length - * Returns: Response (*resp_len bytes) or %NULL on failure - * - * Control interface backends call this function when receiving a message that - * they do not process internally, i.e., anything else than ATTACH, DETACH, - * and LEVEL. The return response value is then sent to the external program - * that sent the command. Caller is responsible for freeing the buffer after - * this. If %NULL is returned, *resp_len can be set to two special values: - * 1 = send "FAIL\n" response, 2 = send "OK\n" response. If *resp_len has any - * other value, no response is sent. - */ -char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, - char *buf, size_t *resp_len); - -/** - * wpa_supplicant_ctrl_iface_process - Process global ctrl_iface command - * @global: Pointer to global data from wpa_supplicant_init() - * @buf: Received command buffer (nul terminated string) - * @resp_len: Variable to be set to the response length - * Returns: Response (*resp_len bytes) or %NULL on failure - * - * Control interface backends call this function when receiving a message from - * the global ctrl_iface connection. The return response value is then sent to - * the external program that sent the command. Caller is responsible for - * freeing the buffer after this. If %NULL is returned, *resp_len can be set to - * two special values: 1 = send "FAIL\n" response, 2 = send "OK\n" response. If - * *resp_len has any other value, no response is sent. - */ -char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global, - char *buf, size_t *resp_len); - - -/* Functions that each ctrl_iface backend must implement */ - -/** - * wpa_supplicant_ctrl_iface_init - Initialize control interface - * @wpa_s: Pointer to wpa_supplicant data - * Returns: Pointer to private data on success, %NULL on failure - * - * Initialize the control interface and start receiving commands from external - * programs. - * - * Required to be implemented in each control interface backend. - */ -struct ctrl_iface_priv * -wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s); - -/** - * wpa_supplicant_ctrl_iface_deinit - Deinitialize control interface - * @priv: Pointer to private data from wpa_supplicant_ctrl_iface_init() - * - * Deinitialize the control interface that was initialized with - * wpa_supplicant_ctrl_iface_init(). - * - * Required to be implemented in each control interface backend. - */ -void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv); - -/** - * wpa_supplicant_ctrl_iface_wait - Wait for ctrl_iface monitor - * @priv: Pointer to private data from wpa_supplicant_ctrl_iface_init() - * - * Wait until the first message from an external program using the control - * interface is received. This function can be used to delay normal startup - * processing to allow control interface programs to attach with - * %wpa_supplicant before normal operations are started. - * - * Required to be implemented in each control interface backend. - */ -void wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv); - -/** - * wpa_supplicant_global_ctrl_iface_init - Initialize global control interface - * @global: Pointer to global data from wpa_supplicant_init() - * Returns: Pointer to private data on success, %NULL on failure - * - * Initialize the global control interface and start receiving commands from - * external programs. - * - * Required to be implemented in each control interface backend. - */ -struct ctrl_iface_global_priv * -wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global); - -/** - * wpa_supplicant_global_ctrl_iface_deinit - Deinitialize global ctrl interface - * @priv: Pointer to private data from wpa_supplicant_global_ctrl_iface_init() - * - * Deinitialize the global control interface that was initialized with - * wpa_supplicant_global_ctrl_iface_init(). - * - * Required to be implemented in each control interface backend. - */ -void wpa_supplicant_global_ctrl_iface_deinit( - struct ctrl_iface_global_priv *priv); - -#else /* CONFIG_CTRL_IFACE */ - -static inline struct ctrl_iface_priv * -wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s) -{ - return (void *) -1; -} - -static inline void -wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv) -{ -} - -static inline void -wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv, int level, - char *buf, size_t len) -{ -} - -static inline void -wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv) -{ -} - -static inline struct ctrl_iface_global_priv * -wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global) -{ - return (void *) 1; -} - -static inline void -wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv) -{ -} - -#endif /* CONFIG_CTRL_IFACE */ - -#endif /* CTRL_IFACE_H */ diff --git a/contrib/wpa_supplicant/ctrl_iface_dbus.c b/contrib/wpa_supplicant/ctrl_iface_dbus.c deleted file mode 100644 index 7475aa42cda0..000000000000 --- a/contrib/wpa_supplicant/ctrl_iface_dbus.c +++ /dev/null @@ -1,1060 +0,0 @@ -/* - * WPA Supplicant / dbus-based control interface - * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, 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 <dbus/dbus.h> - -#include "common.h" -#include "eloop.h" -#include "wpa.h" -#include "wpa_supplicant.h" -#include "config.h" -#include "eapol_sm.h" -#include "wpa_supplicant_i.h" -#include "ctrl_iface_dbus.h" -#include "ctrl_iface_dbus_handlers.h" -#include "l2_packet.h" -#include "preauth.h" -#include "wpa_ctrl.h" -#include "eap.h" - -#define _DBUS_VERSION (DBUS_VERSION_MAJOR << 8 | DBUS_VERSION_MINOR) -#define DBUS_VER(major, minor) ((major) << 8 | (minor)) - -#if _DBUS_VERSION < DBUS_VER(1,1) -#define dbus_watch_get_unix_fd dbus_watch_get_fd -#endif - - -struct ctrl_iface_dbus_priv { - DBusConnection *con; - int should_dispatch; - struct wpa_global *global; - - u32 next_objid; -}; - - -static void process_watch(struct ctrl_iface_dbus_priv *iface, - DBusWatch *watch, eloop_event_type type) -{ - dbus_connection_ref(iface->con); - - iface->should_dispatch = 0; - - if (type == EVENT_TYPE_READ) - dbus_watch_handle(watch, DBUS_WATCH_READABLE); - else if (type == EVENT_TYPE_WRITE) - dbus_watch_handle(watch, DBUS_WATCH_WRITABLE); - else if (type == EVENT_TYPE_EXCEPTION) - dbus_watch_handle(watch, DBUS_WATCH_ERROR); - - if (iface->should_dispatch) { - while (dbus_connection_get_dispatch_status(iface->con) == - DBUS_DISPATCH_DATA_REMAINS) - dbus_connection_dispatch(iface->con); - iface->should_dispatch = 0; - } - - dbus_connection_unref(iface->con); -} - - -static void process_watch_exception(int sock, void *eloop_ctx, void *sock_ctx) -{ - process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_EXCEPTION); -} - - -static void process_watch_read(int sock, void *eloop_ctx, void *sock_ctx) -{ - process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_READ); -} - - -static void process_watch_write(int sock, void *eloop_ctx, void *sock_ctx) -{ - process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_WRITE); -} - - -static void connection_setup_add_watch(struct ctrl_iface_dbus_priv *iface, - DBusWatch *watch) -{ - unsigned int flags; - int fd; - - if (!dbus_watch_get_enabled(watch)) - return; - - flags = dbus_watch_get_flags(watch); - fd = dbus_watch_get_unix_fd(watch); - - eloop_register_sock(fd, EVENT_TYPE_EXCEPTION, process_watch_exception, - iface, watch); - - if (flags & DBUS_WATCH_READABLE) { - eloop_register_sock(fd, EVENT_TYPE_READ, process_watch_read, - iface, watch); - } - if (flags & DBUS_WATCH_WRITABLE) { - eloop_register_sock(fd, EVENT_TYPE_WRITE, process_watch_write, - iface, watch); - } - - dbus_watch_set_data(watch, iface, NULL); -} - - -static void connection_setup_remove_watch(struct ctrl_iface_dbus_priv *iface, - DBusWatch *watch) -{ - unsigned int flags; - int fd; - - flags = dbus_watch_get_flags(watch); - fd = dbus_watch_get_unix_fd(watch); - - eloop_unregister_sock(fd, EVENT_TYPE_EXCEPTION); - - if (flags & DBUS_WATCH_READABLE) - eloop_unregister_sock(fd, EVENT_TYPE_READ); - if (flags & DBUS_WATCH_WRITABLE) - eloop_unregister_sock(fd, EVENT_TYPE_WRITE); - - dbus_watch_set_data(watch, NULL, NULL); -} - - -static dbus_bool_t add_watch(DBusWatch *watch, void *data) -{ - connection_setup_add_watch(data, watch); - return TRUE; -} - - -static void remove_watch(DBusWatch *watch, void *data) -{ - connection_setup_remove_watch(data, watch); -} - - -static void watch_toggled(DBusWatch *watch, void *data) -{ - if (dbus_watch_get_enabled(watch)) - add_watch(watch, data); - else - remove_watch(watch, data); -} - - -static void process_timeout(void *eloop_ctx, void *sock_ctx) -{ - DBusTimeout *timeout = sock_ctx; - - dbus_timeout_handle(timeout); -} - - -static void connection_setup_add_timeout(struct ctrl_iface_dbus_priv *iface, - DBusTimeout *timeout) -{ - if (!dbus_timeout_get_enabled(timeout)) - return; - - eloop_register_timeout(0, dbus_timeout_get_interval(timeout) * 1000, - process_timeout, iface, timeout); - - dbus_timeout_set_data(timeout, iface, NULL); -} - - -static void connection_setup_remove_timeout(struct ctrl_iface_dbus_priv *iface, - DBusTimeout *timeout) -{ - eloop_cancel_timeout(process_timeout, iface, timeout); - dbus_timeout_set_data(timeout, NULL, NULL); -} - - -static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data) -{ - if (!dbus_timeout_get_enabled(timeout)) - return TRUE; - - connection_setup_add_timeout(data, timeout); - - return TRUE; -} - - -static void remove_timeout(DBusTimeout *timeout, void *data) -{ - connection_setup_remove_timeout(data, timeout); -} - - -static void timeout_toggled(DBusTimeout *timeout, void *data) -{ - if (dbus_timeout_get_enabled(timeout)) - add_timeout(timeout, data); - else - remove_timeout(timeout, data); -} - - -static void process_wakeup_main(int sig, void *eloop_ctx, void *signal_ctx) -{ - struct ctrl_iface_dbus_priv *iface = signal_ctx; - - if (sig != SIGPOLL || !iface->con) - return; - - if (dbus_connection_get_dispatch_status(iface->con) != - DBUS_DISPATCH_DATA_REMAINS) - return; - - /* Only dispatch once - we do not want to starve other events */ - dbus_connection_ref(iface->con); - dbus_connection_dispatch(iface->con); - dbus_connection_unref(iface->con); -} - - -/** - * wakeup_main - Attempt to wake our mainloop up - * @data: dbus control interface private data - * - * Try to wake up the main eloop so it will process - * dbus events that may have happened. - */ -static void wakeup_main(void *data) -{ - struct ctrl_iface_dbus_priv *iface = data; - - /* Use SIGPOLL to break out of the eloop select() */ - raise(SIGPOLL); - iface->should_dispatch = 1; -} - - -/** - * connection_setup_wakeup_main - Tell dbus about our wakeup_main function - * @iface: dbus control interface private data - * Returns: 0 on success, -1 on failure - * - * Register our wakeup_main handler with dbus - */ -static int connection_setup_wakeup_main(struct ctrl_iface_dbus_priv *iface) -{ - if (eloop_register_signal(SIGPOLL, process_wakeup_main, iface)) - return -1; - - dbus_connection_set_wakeup_main_function(iface->con, wakeup_main, - iface, NULL); - - return 0; -} - - -/** - * wpa_supplicant_dbus_next_objid - Return next available object id - * @iface: dbus control interface private data - * Returns: Object id - */ -u32 wpa_supplicant_dbus_next_objid (struct ctrl_iface_dbus_priv *iface) -{ - return iface->next_objid++; -} - - -/** - * wpas_dbus_decompose_object_path - Decompose an interface object path into parts - * @path: The dbus object path - * @network: (out) the configured network this object path refers to, if any - * @bssid: (out) the scanned bssid this object path refers to, if any - * Returns: The object path of the network interface this path refers to - * - * For a given object path, decomposes the object path into object id, network, - * and BSSID parts, if those parts exist. - */ -char * wpas_dbus_decompose_object_path(const char *path, char **network, - char **bssid) -{ - const unsigned int dev_path_prefix_len = - strlen(WPAS_DBUS_PATH_INTERFACES "/"); - char *obj_path_only; - char *next_sep; - - /* Be a bit paranoid about path */ - if (!path || strncmp(path, WPAS_DBUS_PATH_INTERFACES "/", - dev_path_prefix_len)) - return NULL; - - /* Ensure there's something at the end of the path */ - if ((path + dev_path_prefix_len)[0] == '\0') - return NULL; - - obj_path_only = strdup(path); - if (obj_path_only == NULL) - return NULL; - - next_sep = strchr(obj_path_only + dev_path_prefix_len, '/'); - if (next_sep != NULL) { - const char *net_part = strstr(next_sep, - WPAS_DBUS_NETWORKS_PART "/"); - const char *bssid_part = strstr(next_sep, - WPAS_DBUS_BSSIDS_PART "/"); - - if (network && net_part) { - /* Deal with a request for a configured network */ - const char *net_name = net_part + - strlen(WPAS_DBUS_NETWORKS_PART "/"); - *network = NULL; - if (strlen(net_name)) - *network = strdup(net_name); - } else if (bssid && bssid_part) { - /* Deal with a request for a scanned BSSID */ - const char *bssid_name = bssid_part + - strlen(WPAS_DBUS_BSSIDS_PART "/"); - if (strlen(bssid_name)) - *bssid = strdup(bssid_name); - else - *bssid = NULL; - } - - /* Cut off interface object path before "/" */ - *next_sep = '\0'; - } - - return obj_path_only; -} - - -/** - * wpas_dbus_new_invalid_iface_error - Return a new invalid interface error message - * @message: Pointer to incoming dbus message this error refers to - * Returns: A dbus error message - * - * Convenience function to create and return an invalid interface error - */ -DBusMessage * wpas_dbus_new_invalid_iface_error(DBusMessage *message) -{ - return dbus_message_new_error(message, WPAS_ERROR_INVALID_IFACE, - "wpa_supplicant knows nothing about " - "this interface."); -} - - -/** - * wpas_dbus_new_invalid_network_error - Return a new invalid network error message - * @message: Pointer to incoming dbus message this error refers to - * Returns: a dbus error message - * - * Convenience function to create and return an invalid network error - */ -DBusMessage * wpas_dbus_new_invalid_network_error(DBusMessage *message) -{ - return dbus_message_new_error(message, WPAS_ERROR_INVALID_NETWORK, - "The requested network does not exist."); -} - - -/** - * wpas_dbus_new_invalid_bssid_error - Return a new invalid bssid error message - * @message: Pointer to incoming dbus message this error refers to - * Returns: a dbus error message - * - * Convenience function to create and return an invalid bssid error - */ -static DBusMessage * wpas_dbus_new_invalid_bssid_error(DBusMessage *message) -{ - return dbus_message_new_error(message, WPAS_ERROR_INVALID_BSSID, - "The BSSID requested was invalid."); -} - - -/** - * wpas_dispatch_network_method - dispatch messages for configured networks - * @message: the incoming dbus message - * @wpa_s: a network interface's data - * @network_id: id of the configured network we're interested in - * Returns: a reply dbus message, or a dbus error message - * - * This function dispatches all incoming dbus messages for configured networks. - */ -static DBusMessage * wpas_dispatch_network_method(DBusMessage *message, - struct wpa_supplicant *wpa_s, - int network_id) -{ - DBusMessage *reply = NULL; - const char *method = dbus_message_get_member(message); - struct wpa_ssid *ssid; - - ssid = wpa_config_get_network(wpa_s->conf, network_id); - if (ssid == NULL) - return wpas_dbus_new_invalid_network_error(message); - - if (!strcmp(method, "set")) - reply = wpas_dbus_iface_set_network(message, wpa_s, ssid); - else if (!strcmp(method, "enable")) - reply = wpas_dbus_iface_enable_network(message, wpa_s, ssid); - else if (!strcmp(method, "disable")) - reply = wpas_dbus_iface_disable_network(message, wpa_s, ssid); - - return reply; -} - - -/** - * wpas_dispatch_bssid_method - dispatch messages for scanned networks - * @message: the incoming dbus message - * @wpa_s: a network interface's data - * @bssid: bssid of the scanned network we're interested in - * Returns: a reply dbus message, or a dbus error message - * - * This function dispatches all incoming dbus messages for scanned networks. - */ -static DBusMessage * wpas_dispatch_bssid_method(DBusMessage *message, - struct wpa_supplicant *wpa_s, - const char *bssid) -{ - DBusMessage *reply = NULL; - const char *method = dbus_message_get_member(message); - struct wpa_scan_result * res = NULL; - int i; - - /* Ensure we actually have scan data */ - if (wpa_s->scan_results == NULL && - wpa_supplicant_get_scan_results(wpa_s) < 0) { - reply = wpas_dbus_new_invalid_bssid_error(message); - goto out; - } - - /* Find the bssid's scan data */ - for (i = 0; i < wpa_s->num_scan_results; i++) { - struct wpa_scan_result * search_res = &wpa_s->scan_results[i]; - char mac_str[18]; - - memset(mac_str, 0, sizeof(mac_str)); - snprintf(mac_str, sizeof(mac_str) - 1, WPAS_DBUS_BSSID_FORMAT, - MAC2STR(search_res->bssid)); - if (!strcmp(bssid, mac_str)) { - res = search_res; - } - } - - if (!res) { - reply = wpas_dbus_new_invalid_bssid_error(message); - goto out; - } - - /* Dispatch the method call against the scanned bssid */ - if (!strcmp(method, "properties")) - reply = wpas_dbus_bssid_properties(message, wpa_s, res); - -out: - return reply; -} - - -/** - * wpas_iface_message_handler - Dispatch messages for interfaces or networks - * @connection: Connection to the system message bus - * @message: An incoming dbus message - * @user_data: A pointer to a dbus control interface data structure - * Returns: Whether or not the message was handled - * - * This function dispatches all incoming dbus messages for network interfaces, - * or objects owned by them, such as scanned BSSIDs and configured networks. - */ -static DBusHandlerResult wpas_iface_message_handler(DBusConnection *connection, - DBusMessage *message, - void *user_data) -{ - struct wpa_supplicant *wpa_s = user_data; - const char *method = dbus_message_get_member(message); - const char *path = dbus_message_get_path(message); - const char *msg_interface = dbus_message_get_interface(message); - char *iface_obj_path = NULL; - char *network = NULL; - char *bssid = NULL; - DBusMessage *reply = NULL; - - /* Caller must specify a message interface */ - if (!msg_interface) - goto out; - - iface_obj_path = wpas_dbus_decompose_object_path(path, &network, - &bssid); - if (iface_obj_path == NULL) { - reply = wpas_dbus_new_invalid_iface_error(message); - goto out; - } - - /* Make sure the message's object path actually refers to the - * wpa_supplicant structure it's supposed to (which is wpa_s) - */ - if (wpa_supplicant_get_iface_by_dbus_path(wpa_s->global, - iface_obj_path) != wpa_s) { - reply = wpas_dbus_new_invalid_iface_error(message); - goto out; - } - - if (network && !strcmp(msg_interface, WPAS_DBUS_IFACE_NETWORK)) { - /* A method for one of this interface's configured networks */ - int nid = strtoul(network, NULL, 10); - if (errno != EINVAL) - reply = wpas_dispatch_network_method(message, wpa_s, - nid); - else - reply = wpas_dbus_new_invalid_network_error(message); - } else if (bssid && !strcmp(msg_interface, WPAS_DBUS_IFACE_BSSID)) { - /* A method for one of this interface's scanned BSSIDs */ - reply = wpas_dispatch_bssid_method(message, wpa_s, bssid); - } else if (!strcmp(msg_interface, WPAS_DBUS_IFACE_INTERFACE)) { - /* A method for an interface only. */ - if (!strcmp(method, "scan")) - reply = wpas_dbus_iface_scan(message, wpa_s); - else if (!strcmp(method, "scanResults")) - reply = wpas_dbus_iface_scan_results(message, wpa_s); - else if (!strcmp(method, "addNetwork")) - reply = wpas_dbus_iface_add_network(message, wpa_s); - else if (!strcmp(method, "removeNetwork")) - reply = wpas_dbus_iface_remove_network(message, wpa_s); - else if (!strcmp(method, "selectNetwork")) - reply = wpas_dbus_iface_select_network(message, wpa_s); - else if (!strcmp(method, "capabilities")) - reply = wpas_dbus_iface_capabilities(message, wpa_s); - else if (!strcmp(method, "disconnect")) - reply = wpas_dbus_iface_disconnect(message, wpa_s); - else if (!strcmp(method, "setAPScan")) - reply = wpas_dbus_iface_set_ap_scan(message, wpa_s); - else if (!strcmp(method, "state")) - reply = wpas_dbus_iface_get_state(message, wpa_s); - else if (!strcmp(method, "setBlobs")) - reply = wpas_dbus_iface_set_blobs(message, wpa_s); - else if (!strcmp(method, "removeBlobs")) - reply = wpas_dbus_iface_remove_blobs(message, wpa_s); - } - - /* If the message was handled, send back the reply */ - if (reply) { - dbus_connection_send(connection, reply, NULL); - dbus_message_unref(reply); - } - -out: - free(iface_obj_path); - free(network); - free(bssid); - return reply ? DBUS_HANDLER_RESULT_HANDLED : - DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - - -/** - * wpas_message_handler - dispatch incoming dbus messages - * @connection: connection to the system message bus - * @message: an incoming dbus message - * @user_data: a pointer to a dbus control interface data structure - * Returns: whether or not the message was handled - * - * This function dispatches all incoming dbus messages to the correct - * handlers, depending on what the message's target object path is, - * and what the method call is. - */ -static DBusHandlerResult wpas_message_handler(DBusConnection *connection, - DBusMessage *message, void *user_data) -{ - struct ctrl_iface_dbus_priv *ctrl_iface = user_data; - const char *method; - const char *path; - const char *msg_interface; - DBusMessage *reply = NULL; - - method = dbus_message_get_member(message); - path = dbus_message_get_path(message); - msg_interface = dbus_message_get_interface(message); - if (!method || !path || !ctrl_iface || !msg_interface) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - /* Validate the method interface */ - if (strcmp(msg_interface, WPAS_DBUS_INTERFACE) != 0) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - - if (!strcmp(path, WPAS_DBUS_PATH)) { - /* dispatch methods against our global dbus interface here */ - if (!strcmp(method, "addInterface")) { - reply = wpas_dbus_global_add_interface( - message, ctrl_iface->global); - } else if (!strcmp(method, "removeInterface")) { - reply = wpas_dbus_global_remove_interface( - message, ctrl_iface->global); - } else if (!strcmp(method, "getInterface")) { - reply = wpas_dbus_global_get_interface( - message, ctrl_iface->global); - } - } - - /* If the message was handled, send back the reply */ - if (reply) { - dbus_connection_send(connection, reply, NULL); - dbus_message_unref(reply); - } - - return reply ? DBUS_HANDLER_RESULT_HANDLED : - DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - - -/** - * wpa_supplicant_dbus_notify_scan_results - Send a scan results signal - * @wpa_s: %wpa_supplicant network interface data - * Returns: 0 on success, -1 on failure - * - * Notify listeners that this interface has updated scan results. - */ -void wpa_supplicant_dbus_notify_scan_results(struct wpa_supplicant *wpa_s) -{ - struct ctrl_iface_dbus_priv *iface = wpa_s->global->dbus_ctrl_iface; - DBusMessage *signal; - const char *path; - - /* Do nothing if the control interface is not turned on */ - if (iface == NULL) - return; - - path = wpa_supplicant_get_dbus_path(wpa_s); - if (path == NULL) { - perror("wpa_supplicant_dbus_notify_scan_results[dbus]: " - "interface didn't have a dbus path"); - wpa_printf(MSG_ERROR, - "wpa_supplicant_dbus_notify_scan_results[dbus]: " - "interface didn't have a dbus path; can't send " - "scan result signal."); - return; - } - signal = dbus_message_new_signal(path, WPAS_DBUS_IFACE_INTERFACE, - "ScanResultsAvailable"); - if (signal == NULL) { - perror("wpa_supplicant_dbus_notify_scan_results[dbus]: " - "couldn't create dbus signal; likely out of memory"); - wpa_printf(MSG_ERROR, "dbus control interface: not enough " - "memory to send scan results signal."); - return; - } - dbus_connection_send(iface->con, signal, NULL); - dbus_message_unref(signal); -} - - -/** - * wpa_supplicant_dbus_notify_state_change - Send a state change signal - * @wpa_s: %wpa_supplicant network interface data - * @new_state: new state wpa_supplicant is entering - * @old_state: old state wpa_supplicant is leaving - * Returns: 0 on success, -1 on failure - * - * Notify listeners that wpa_supplicant has changed state - */ -void wpa_supplicant_dbus_notify_state_change(struct wpa_supplicant *wpa_s, - wpa_states new_state, - wpa_states old_state) -{ - struct ctrl_iface_dbus_priv *iface; - DBusMessage *signal = NULL; - const char *path; - const char *new_state_str, *old_state_str; - - /* Do nothing if the control interface is not turned on */ - if (wpa_s->global == NULL) - return; - iface = wpa_s->global->dbus_ctrl_iface; - if (iface == NULL) - return; - - /* Only send signal if state really changed */ - if (new_state == old_state) - return; - - path = wpa_supplicant_get_dbus_path(wpa_s); - if (path == NULL) { - perror("wpa_supplicant_dbus_notify_state_change[dbus]: " - "interface didn't have a dbus path"); - wpa_printf(MSG_ERROR, - "wpa_supplicant_dbus_notify_state_change[dbus]: " - "interface didn't have a dbus path; can't send " - "signal."); - return; - } - signal = dbus_message_new_signal(path, WPAS_DBUS_IFACE_INTERFACE, - "StateChange"); - if (signal == NULL) { - perror("wpa_supplicant_dbus_notify_state_change[dbus]: " - "couldn't create dbus signal; likely out of memory"); - wpa_printf(MSG_ERROR, - "wpa_supplicant_dbus_notify_state_change[dbus]: " - "couldn't create dbus signal; likely out of " - "memory."); - return; - } - - new_state_str = wpa_supplicant_state_txt(new_state); - old_state_str = wpa_supplicant_state_txt(old_state); - if (new_state_str == NULL || old_state_str == NULL) { - perror("wpa_supplicant_dbus_notify_state_change[dbus]: " - "couldn't convert state strings"); - wpa_printf(MSG_ERROR, - "wpa_supplicant_dbus_notify_state_change[dbus]: " - "couldn't convert state strings."); - goto out; - } - - if (!dbus_message_append_args(signal, - DBUS_TYPE_STRING, &new_state_str, - DBUS_TYPE_STRING, &old_state_str, - DBUS_TYPE_INVALID)) { - perror("wpa_supplicant_dbus_notify_state_change[dbus]: " - "not enough memory to construct state change signal."); - wpa_printf(MSG_ERROR, - "wpa_supplicant_dbus_notify_state_change[dbus]: " - "not enough memory to construct state change " - "signal."); - goto out; - } - dbus_connection_send(iface->con, signal, NULL); - -out: - dbus_message_unref(signal); -} - - -/** - * integrate_with_eloop - Register our mainloop integration with dbus - * @connection: connection to the system message bus - * @iface: a dbus control interface data structure - * Returns: 0 on success, -1 on failure - * - * We register our mainloop integration functions with dbus here. - */ -static int integrate_with_eloop(DBusConnection *connection, - struct ctrl_iface_dbus_priv *iface) -{ - if (!dbus_connection_set_watch_functions(connection, add_watch, - remove_watch, watch_toggled, - iface, NULL)) { - perror("dbus_connection_set_watch_functions[dbus]"); - wpa_printf(MSG_ERROR, "Not enough memory to set up dbus."); - return -1; - } - - if (!dbus_connection_set_timeout_functions(connection, add_timeout, - remove_timeout, - timeout_toggled, iface, - NULL)) { - perror("dbus_connection_set_timeout_functions[dbus]"); - wpa_printf(MSG_ERROR, "Not enough memory to set up dbus."); - return -1; - } - - if (connection_setup_wakeup_main(iface) < 0) { - perror("connection_setup_wakeup_main[dbus]"); - wpa_printf(MSG_ERROR, "Could not setup main wakeup function."); - return -1; - } - - return 0; -} - - -/** - * dispatch_initial_dbus_messages - Dispatch initial dbus messages after - * claiming bus name - * @eloop_ctx: the DBusConnection to dispatch on - * @timeout_ctx: unused - * - * If clients are quick to notice that wpa_supplicant claimed its bus name, - * there may have been messages that came in before initialization was - * all finished. Dispatch those here. - */ -static void dispatch_initial_dbus_messages(void *eloop_ctx, void *timeout_ctx) -{ - DBusConnection *con = eloop_ctx; - - while (dbus_connection_get_dispatch_status(con) == - DBUS_DISPATCH_DATA_REMAINS) - dbus_connection_dispatch(con); -} - - -/** - * wpa_supplicant_dbus_ctrl_iface_init - Initialize dbus control interface - * @global: Pointer to global data from wpa_supplicant_init() - * Returns: Pointer to dbus_ctrl_iface date or %NULL on failure - * - * Initialize the dbus control interface and start receiving commands from - * external programs over the bus. - */ -struct ctrl_iface_dbus_priv * -wpa_supplicant_dbus_ctrl_iface_init(struct wpa_global *global) -{ - struct ctrl_iface_dbus_priv *iface; - DBusError error; - int ret = -1; - DBusObjectPathVTable wpas_vtable = { - NULL, &wpas_message_handler, NULL, NULL, NULL, NULL - }; - - iface = wpa_zalloc(sizeof(struct ctrl_iface_dbus_priv)); - if (iface == NULL) - return NULL; - - iface->global = global; - - /* Get a reference to the system bus */ - dbus_error_init(&error); - iface->con = dbus_bus_get(DBUS_BUS_SYSTEM, &error); - dbus_error_free(&error); - if (!iface->con) { - perror("dbus_bus_get[ctrl_iface_dbus]"); - wpa_printf(MSG_ERROR, "Could not acquire the system bus."); - goto fail; - } - - /* Tell dbus about our mainloop integration functions */ - if (integrate_with_eloop(iface->con, iface)) - goto fail; - - /* Register the message handler for the global dbus interface */ - if (!dbus_connection_register_object_path(iface->con, - WPAS_DBUS_PATH, &wpas_vtable, - iface)) { - perror("dbus_connection_register_object_path[dbus]"); - wpa_printf(MSG_ERROR, "Could not set up DBus message " - "handler."); - goto fail; - } - - /* Register our service with the message bus */ - dbus_error_init(&error); - switch (dbus_bus_request_name(iface->con, WPAS_DBUS_SERVICE, - 0, &error)) { - case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER: - ret = 0; - break; - case DBUS_REQUEST_NAME_REPLY_EXISTS: - case DBUS_REQUEST_NAME_REPLY_IN_QUEUE: - case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER: - perror("dbus_bus_request_name[dbus]"); - wpa_printf(MSG_ERROR, "Could not request DBus service name: " - "already registered."); - break; - default: - perror("dbus_bus_request_name[dbus]"); - wpa_printf(MSG_ERROR, "Could not request DBus service name: " - "%s %s.", error.name, error.message); - break; - } - dbus_error_free(&error); - - if (ret != 0) - goto fail; - - wpa_printf(MSG_DEBUG, "Providing DBus service '" WPAS_DBUS_SERVICE - "'."); - - /* - * Dispatch initial DBus messages that may have come in since the bus - * name was claimed above. Happens when clients are quick to notice the - * wpa_supplicant service. - * - * FIXME: is there a better solution to this problem? - */ - eloop_register_timeout(0, 50, dispatch_initial_dbus_messages, - iface->con, NULL); - - return iface; - -fail: - wpa_supplicant_dbus_ctrl_iface_deinit(iface); - return NULL; -} - - -/** - * wpa_supplicant_dbus_ctrl_iface_deinit - Deinitialize dbus ctrl interface - * @iface: Pointer to dbus private data from - * wpa_supplicant_dbus_ctrl_iface_init() - * - * Deinitialize the dbus control interface that was initialized with - * wpa_supplicant_dbus_ctrl_iface_init(). - */ -void wpa_supplicant_dbus_ctrl_iface_deinit(struct ctrl_iface_dbus_priv *iface) -{ - if (iface == NULL) - return; - - if (iface->con) { - eloop_cancel_timeout(dispatch_initial_dbus_messages, - iface->con, NULL); - dbus_connection_set_watch_functions(iface->con, NULL, NULL, - NULL, NULL, NULL); - dbus_connection_set_timeout_functions(iface->con, NULL, NULL, - NULL, NULL, NULL); - dbus_connection_unref(iface->con); - } - - memset(iface, 0, sizeof(struct ctrl_iface_dbus_priv)); - free(iface); -} - - -/** - * wpas_dbus_register_new_iface - Register a new interface with dbus - * @global: Global %wpa_supplicant data - * @wpa_s: %wpa_supplicant interface description structure to register - * Returns: 0 on success, -1 on error - * - * Registers a new interface with dbus and assigns it a dbus object path. - */ -int wpas_dbus_register_iface(struct wpa_supplicant *wpa_s) -{ - struct ctrl_iface_dbus_priv *ctrl_iface = - wpa_s->global->dbus_ctrl_iface; - DBusConnection * con; - u32 next; - DBusObjectPathVTable vtable = { - NULL, &wpas_iface_message_handler, NULL, NULL, NULL, NULL - }; - char *path; - int ret = -1; - - /* Do nothing if the control interface is not turned on */ - if (ctrl_iface == NULL) - return 0; - - con = ctrl_iface->con; - next = wpa_supplicant_dbus_next_objid(ctrl_iface); - - /* Create and set the interface's object path */ - path = wpa_zalloc(WPAS_DBUS_OBJECT_PATH_MAX); - if (path == NULL) - return -1; - snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX, - WPAS_DBUS_PATH_INTERFACES "/%u", - next); - if (wpa_supplicant_set_dbus_path(wpa_s, path)) { - wpa_printf(MSG_DEBUG, - "Failed to set dbus path for interface %s", - wpa_s->ifname); - goto out; - } - - /* Register the message handler for the interface functions */ - if (!dbus_connection_register_fallback(con, path, &vtable, wpa_s)) { - perror("wpas_dbus_register_iface [dbus]"); - wpa_printf(MSG_ERROR, "Could not set up DBus message " - "handler for interface %s.", wpa_s->ifname); - goto out; - } - ret = 0; - -out: - free(path); - return ret; -} - - -/** - * wpas_dbus_unregister_iface - Unregister an interface from dbus - * @wpa_s: wpa_supplicant interface structure - * Returns: 0 on success, -1 on failure - * - * Unregisters the interface with dbus - */ -int wpas_dbus_unregister_iface(struct wpa_supplicant *wpa_s) -{ - struct ctrl_iface_dbus_priv *ctrl_iface; - DBusConnection *con; - const char *path; - - /* Do nothing if the control interface is not turned on */ - if (wpa_s == NULL || wpa_s->global == NULL) - return 0; - ctrl_iface = wpa_s->global->dbus_ctrl_iface; - if (ctrl_iface == NULL) - return 0; - - con = ctrl_iface->con; - path = wpa_supplicant_get_dbus_path(wpa_s); - - if (!dbus_connection_unregister_object_path(con, path)) - return -1; - - free(wpa_s->dbus_path); - wpa_s->dbus_path = NULL; - - return 0; -} - - -/** - * wpa_supplicant_get_iface_by_dbus_path - Get a new network interface - * @global: Pointer to global data from wpa_supplicant_init() - * @path: Pointer to a dbus object path representing an interface - * Returns: Pointer to the interface or %NULL if not found - */ -struct wpa_supplicant * wpa_supplicant_get_iface_by_dbus_path( - struct wpa_global *global, const char *path) -{ - struct wpa_supplicant *wpa_s; - - for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { - if (strcmp(wpa_s->dbus_path, path) == 0) - return wpa_s; - } - return NULL; -} - - -/** - * wpa_supplicant_set_dbus_path - Assign a dbus path to an interface - * @wpa_s: wpa_supplicant interface structure - * @path: dbus path to set on the interface - * Returns: 0 on succes, -1 on error - */ -int wpa_supplicant_set_dbus_path(struct wpa_supplicant *wpa_s, - const char *path) -{ - u32 len = strlen (path); - if (len >= WPAS_DBUS_OBJECT_PATH_MAX) - return -1; - if (wpa_s->dbus_path) - return -1; - wpa_s->dbus_path = strdup(path); - return 0; -} - - -/** - * wpa_supplicant_get_dbus_path - Get an interface's dbus path - * @wpa_s: %wpa_supplicant interface structure - * Returns: Interface's dbus object path, or %NULL on error - */ -const char * wpa_supplicant_get_dbus_path(struct wpa_supplicant *wpa_s) -{ - return wpa_s->dbus_path; -} diff --git a/contrib/wpa_supplicant/ctrl_iface_dbus.h b/contrib/wpa_supplicant/ctrl_iface_dbus.h deleted file mode 100644 index b66c179c596e..000000000000 --- a/contrib/wpa_supplicant/ctrl_iface_dbus.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - * WPA Supplicant / dbus-based control interface - * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, 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 CTRL_IFACE_DBUS_H -#define CTRL_IFACE_DBUS_H - -#ifdef CONFIG_CTRL_IFACE_DBUS - -#ifndef SIGPOLL -#ifdef SIGIO -/* - * If we do not have SIGPOLL, try to use SIGIO instead. This is needed for - * FreeBSD. - */ -#define SIGPOLL SIGIO -#endif -#endif - -#include <dbus/dbus.h> - -#define WPAS_DBUS_OBJECT_PATH_MAX 150 - -#define WPAS_DBUS_SERVICE "fi.epitest.hostap.WPASupplicant" -#define WPAS_DBUS_PATH "/fi/epitest/hostap/WPASupplicant" -#define WPAS_DBUS_INTERFACE "fi.epitest.hostap.WPASupplicant" - -#define WPAS_DBUS_PATH_INTERFACES WPAS_DBUS_PATH "/Interfaces" -#define WPAS_DBUS_IFACE_INTERFACE WPAS_DBUS_INTERFACE ".Interface" - -#define WPAS_DBUS_NETWORKS_PART "Networks" -#define WPAS_DBUS_IFACE_NETWORK WPAS_DBUS_INTERFACE ".Network" - -#define WPAS_DBUS_BSSIDS_PART "BSSIDs" -#define WPAS_DBUS_IFACE_BSSID WPAS_DBUS_INTERFACE ".BSSID" - - -/* Errors */ -#define WPAS_ERROR_INVALID_NETWORK \ - WPAS_DBUS_IFACE_INTERFACE ".InvalidNetwork" -#define WPAS_ERROR_INVALID_BSSID \ - WPAS_DBUS_IFACE_INTERFACE ".InvalidBSSID" - -#define WPAS_ERROR_INVALID_OPTS \ - WPAS_DBUS_INTERFACE ".InvalidOptions" -#define WPAS_ERROR_INVALID_IFACE \ - WPAS_DBUS_INTERFACE ".InvalidInterface" - -#define WPAS_ERROR_ADD_ERROR \ - WPAS_DBUS_INTERFACE ".AddError" -#define WPAS_ERROR_EXISTS_ERROR \ - WPAS_DBUS_INTERFACE ".ExistsError" -#define WPAS_ERROR_REMOVE_ERROR \ - WPAS_DBUS_INTERFACE ".RemoveError" - -#define WPAS_ERROR_SCAN_ERROR \ - WPAS_DBUS_IFACE_INTERFACE ".ScanError" -#define WPAS_ERROR_ADD_NETWORK_ERROR \ - WPAS_DBUS_IFACE_INTERFACE ".AddNetworkError" -#define WPAS_ERROR_INTERNAL_ERROR \ - WPAS_DBUS_IFACE_INTERFACE ".InternalError" -#define WPAS_ERROR_REMOVE_NETWORK_ERROR \ - WPAS_DBUS_IFACE_INTERFACE ".RemoveNetworkError" - -#define WPAS_DBUS_BSSID_FORMAT "%02x%02x%02x%02x%02x%02x" - -struct wpa_global; -struct wpa_supplicant; - -struct ctrl_iface_dbus_priv * -wpa_supplicant_dbus_ctrl_iface_init(struct wpa_global *global); -void wpa_supplicant_dbus_ctrl_iface_deinit(struct ctrl_iface_dbus_priv *iface); -void wpa_supplicant_dbus_notify_scan_results(struct wpa_supplicant *wpa_s); -void wpa_supplicant_dbus_notify_state_change(struct wpa_supplicant *wpa_s, - wpa_states new_state, - wpa_states old_state); - -char * wpas_dbus_decompose_object_path(const char *path, char **network, - char **bssid); - -int wpas_dbus_register_iface(struct wpa_supplicant *wpa_s); -int wpas_dbus_unregister_iface(struct wpa_supplicant *wpa_s); - - -/* Methods internal to the dbus control interface */ -u32 wpa_supplicant_dbus_next_objid(struct ctrl_iface_dbus_priv *iface); - -int wpa_supplicant_set_dbus_path(struct wpa_supplicant *wpa_s, - const char *path); -const char *wpa_supplicant_get_dbus_path(struct wpa_supplicant *wpa_s); -struct wpa_supplicant * wpa_supplicant_get_iface_by_dbus_path( - struct wpa_global *global, const char *path); - -DBusMessage * wpas_dbus_new_invalid_iface_error(DBusMessage *message); -DBusMessage * wpas_dbus_new_invalid_network_error(DBusMessage *message); - -#else /* CONFIG_CTRL_IFACE_DBUS */ - -static inline struct ctrl_iface_dbus_priv * -wpa_supplicant_dbus_ctrl_iface_init(struct wpa_global *global) -{ - return (struct ctrl_iface_dbus_priv *) 1; -} - -static inline void -wpa_supplicant_dbus_ctrl_iface_deinit(struct ctrl_iface_dbus_priv *iface) -{ -} - -static inline void -wpa_supplicant_dbus_notify_scan_results(struct wpa_supplicant *wpa_s) -{ -} - -static inline void -wpa_supplicant_dbus_notify_state_change(struct wpa_supplicant *wpa_s, - wpa_states new_state, - wpa_states old_state) -{ -} - -static inline int -wpas_dbus_register_iface(struct wpa_supplicant *wpa_s) -{ - return 0; -} - -static inline int -wpas_dbus_unregister_iface(struct wpa_supplicant *wpa_s) -{ - return 0; -} - -#endif /* CONFIG_CTRL_IFACE_DBUS */ - -#endif /* CTRL_IFACE_DBUS_H */ diff --git a/contrib/wpa_supplicant/ctrl_iface_dbus_handlers.c b/contrib/wpa_supplicant/ctrl_iface_dbus_handlers.c deleted file mode 100644 index 19972c008045..000000000000 --- a/contrib/wpa_supplicant/ctrl_iface_dbus_handlers.c +++ /dev/null @@ -1,1331 +0,0 @@ -/* - * WPA Supplicant / dbus-based control interface - * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, 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 <dbus/dbus.h> - -#include "common.h" -#include "config.h" -#include "wpa_supplicant_i.h" -#include "ctrl_iface_dbus.h" -#include "ctrl_iface_dbus_handlers.h" -#include "l2_packet.h" -#include "eap_methods.h" -#include "dbus_dict_helpers.h" -#include "wpa.h" - - -/** - * wpas_dbus_new_invalid_opts_error - Return a new invalid options error message - * @message: Pointer to incoming dbus message this error refers to - * Returns: a dbus error message - * - * Convenience function to create and return an invalid options error - */ -static DBusMessage * wpas_dbus_new_invalid_opts_error(DBusMessage *message, - const char *arg) -{ - DBusMessage *reply; - - reply = dbus_message_new_error(message, WPAS_ERROR_INVALID_OPTS, - "Did not receive correct message " - "arguments."); - if (arg != NULL) - dbus_message_append_args(reply, DBUS_TYPE_STRING, &arg, - DBUS_TYPE_INVALID); - - return reply; -} - - -/** - * wpas_dbus_new_success_reply - Return a new success reply message - * @message: Pointer to incoming dbus message this reply refers to - * Returns: a dbus message containing a single UINT32 that indicates - * success (ie, a value of 1) - * - * Convenience function to create and return a success reply message - */ -static DBusMessage * wpas_dbus_new_success_reply(DBusMessage *message) -{ - DBusMessage *reply; - unsigned int success = 1; - - reply = dbus_message_new_method_return(message); - dbus_message_append_args(reply, DBUS_TYPE_UINT32, &success, - DBUS_TYPE_INVALID); - return reply; -} - - -static void wpas_dbus_free_wpa_interface(struct wpa_interface *iface) -{ - free((char *) iface->driver); - free((char *) iface->driver_param); - free((char *) iface->confname); - free((char *) iface->bridge_ifname); -} - - -/** - * wpas_dbus_global_add_interface - Request registration of a network interface - * @message: Pointer to incoming dbus message - * @global: %wpa_supplicant global data structure - * Returns: The object path of the new interface object, - * or a dbus error message with more information - * - * Handler function for "addInterface" method call. Handles requests - * by dbus clients to register a network interface that wpa_supplicant - * will manage. - */ -DBusMessage * wpas_dbus_global_add_interface(DBusMessage *message, - struct wpa_global *global) -{ - struct wpa_interface iface; - char *ifname = NULL; - DBusMessage *reply = NULL; - DBusMessageIter iter; - - memset(&iface, 0, sizeof(iface)); - - dbus_message_iter_init(message, &iter); - - /* First argument: interface name (DBUS_TYPE_STRING) - * Required; must be non-zero length - */ - if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) - goto error; - dbus_message_iter_get_basic(&iter, &ifname); - if (!strlen(ifname)) - goto error; - iface.ifname = ifname; - - /* Second argument: dict of options */ - if (dbus_message_iter_next(&iter)) { - DBusMessageIter iter_dict; - struct wpa_dbus_dict_entry entry; - - if (!wpa_dbus_dict_open_read(&iter, &iter_dict)) - goto error; - while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { - if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) - goto error; - if (!strcmp(entry.key, "driver") && - (entry.type == DBUS_TYPE_STRING)) { - iface.driver = strdup(entry.str_value); - if (iface.driver == NULL) - goto error; - } else if (!strcmp(entry.key, "driver-params") && - (entry.type == DBUS_TYPE_STRING)) { - iface.driver_param = strdup(entry.str_value); - if (iface.driver_param == NULL) - goto error; - } else if (!strcmp(entry.key, "config-file") && - (entry.type == DBUS_TYPE_STRING)) { - iface.confname = strdup(entry.str_value); - if (iface.confname == NULL) - goto error; - } else if (!strcmp(entry.key, "bridge-ifname") && - (entry.type == DBUS_TYPE_STRING)) { - iface.bridge_ifname = strdup(entry.str_value); - if (iface.bridge_ifname == NULL) - goto error; - } else { - wpa_dbus_dict_entry_clear(&entry); - goto error; - } - wpa_dbus_dict_entry_clear(&entry); - } - } - - /* - * Try to get the wpa_supplicant record for this iface, return - * an error if we already control it. - */ - if (wpa_supplicant_get_iface(global, iface.ifname) != 0) { - reply = dbus_message_new_error(message, - WPAS_ERROR_EXISTS_ERROR, - "wpa_supplicant already " - "controls this interface."); - } else { - struct wpa_supplicant *wpa_s; - /* Otherwise, have wpa_supplicant attach to it. */ - if ((wpa_s = wpa_supplicant_add_iface(global, &iface))) { - const char *path = wpa_supplicant_get_dbus_path(wpa_s); - reply = dbus_message_new_method_return(message); - dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, - &path, DBUS_TYPE_INVALID); - } else { - reply = dbus_message_new_error(message, - WPAS_ERROR_ADD_ERROR, - "wpa_supplicant " - "couldn't grab this " - "interface."); - } - } - wpas_dbus_free_wpa_interface(&iface); - return reply; - -error: - wpas_dbus_free_wpa_interface(&iface); - return wpas_dbus_new_invalid_opts_error(message, NULL); -} - - -/** - * wpas_dbus_global_remove_interface - Request deregistration of an interface - * @message: Pointer to incoming dbus message - * @global: wpa_supplicant global data structure - * Returns: a dbus message containing a UINT32 indicating success (1) or - * failure (0), or returns a dbus error message with more information - * - * Handler function for "removeInterface" method call. Handles requests - * by dbus clients to deregister a network interface that wpa_supplicant - * currently manages. - */ -DBusMessage * wpas_dbus_global_remove_interface(DBusMessage *message, - struct wpa_global *global) -{ - struct wpa_supplicant *wpa_s; - char *path; - DBusMessage *reply = NULL; - - if (!dbus_message_get_args(message, NULL, - DBUS_TYPE_OBJECT_PATH, &path, - DBUS_TYPE_INVALID)) { - reply = wpas_dbus_new_invalid_opts_error(message, NULL); - goto out; - } - - wpa_s = wpa_supplicant_get_iface_by_dbus_path(global, path); - if (wpa_s == NULL) { - reply = wpas_dbus_new_invalid_iface_error(message); - goto out; - } - - if (!wpa_supplicant_remove_iface(global, wpa_s)) { - reply = wpas_dbus_new_success_reply(message); - } else { - reply = dbus_message_new_error(message, - WPAS_ERROR_REMOVE_ERROR, - "wpa_supplicant couldn't " - "remove this interface."); - } - -out: - return reply; -} - - -/** - * wpas_dbus_global_get_interface - Get the object path for an interface name - * @message: Pointer to incoming dbus message - * @global: %wpa_supplicant global data structure - * Returns: The object path of the interface object, - * or a dbus error message with more information - * - * Handler function for "getInterface" method call. Handles requests - * by dbus clients for the object path of an specific network interface. - */ -DBusMessage * wpas_dbus_global_get_interface(DBusMessage *message, - struct wpa_global *global) -{ - DBusMessage *reply = NULL; - const char *ifname; - const char *path; - struct wpa_supplicant *wpa_s; - - if (!dbus_message_get_args(message, NULL, - DBUS_TYPE_STRING, &ifname, - DBUS_TYPE_INVALID)) { - reply = wpas_dbus_new_invalid_opts_error(message, NULL); - goto out; - } - - wpa_s = wpa_supplicant_get_iface(global, ifname); - if (wpa_s == NULL) { - reply = wpas_dbus_new_invalid_iface_error(message); - goto out; - } - - path = wpa_supplicant_get_dbus_path(wpa_s); - if (path == NULL) { - reply = dbus_message_new_error(message, - WPAS_ERROR_INTERNAL_ERROR, - "an internal error occurred " - "getting the interface."); - goto out; - } - - reply = dbus_message_new_method_return(message); - dbus_message_append_args(reply, - DBUS_TYPE_OBJECT_PATH, &path, - DBUS_TYPE_INVALID); - -out: - return reply; -} - - -/** - * wpas_dbus_iface_scan - Request a wireless scan on an interface - * @message: Pointer to incoming dbus message - * @wpa_s: wpa_supplicant structure for a network interface - * Returns: a dbus message containing a UINT32 indicating success (1) or - * failure (0) - * - * Handler function for "scan" method call of a network device. Requests - * that wpa_supplicant perform a wireless scan as soon as possible - * on a particular wireless interface. - */ -DBusMessage * wpas_dbus_iface_scan(DBusMessage *message, - struct wpa_supplicant *wpa_s) -{ - wpa_s->scan_req = 2; - wpa_supplicant_req_scan(wpa_s, 0, 0); - return wpas_dbus_new_success_reply(message); -} - - -/** - * wpas_dbus_iface_scan_results - Get the results of a recent scan request - * @message: Pointer to incoming dbus message - * @wpa_s: wpa_supplicant structure for a network interface - * Returns: a dbus message containing a dbus array of objects paths, or returns - * a dbus error message if not scan results could be found - * - * Handler function for "scanResults" method call of a network device. Returns - * a dbus message containing the object paths of wireless networks found. - */ -DBusMessage * wpas_dbus_iface_scan_results(DBusMessage *message, - struct wpa_supplicant *wpa_s) -{ - DBusMessage *reply = NULL; - DBusMessageIter iter; - DBusMessageIter sub_iter; - int i; - - /* Ensure we've actually got scan results to return */ - if (wpa_s->scan_results == NULL && - wpa_supplicant_get_scan_results(wpa_s) < 0) { - reply = dbus_message_new_error(message, WPAS_ERROR_SCAN_ERROR, - "An error ocurred getting scan " - "results."); - goto out; - } - - /* Create and initialize the return message */ - reply = dbus_message_new_method_return(message); - dbus_message_iter_init_append(reply, &iter); - dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, - DBUS_TYPE_OBJECT_PATH_AS_STRING, - &sub_iter); - - /* Loop through scan results and append each result's object path */ - for (i = 0; i < wpa_s->num_scan_results; i++) { - struct wpa_scan_result *res = &wpa_s->scan_results[i]; - char *path; - - path = wpa_zalloc(WPAS_DBUS_OBJECT_PATH_MAX); - if (path == NULL) { - perror("wpas_dbus_iface_scan_results[dbus]: out of " - "memory."); - wpa_printf(MSG_ERROR, "dbus control interface: not " - "enough memory to send scan results " - "signal."); - break; - } - /* Construct the object path for this network. Note that ':' - * is not a valid character in dbus object paths. - */ - snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX, - "%s/" WPAS_DBUS_BSSIDS_PART "/" - WPAS_DBUS_BSSID_FORMAT, - wpa_supplicant_get_dbus_path(wpa_s), - MAC2STR(res->bssid)); - dbus_message_iter_append_basic(&sub_iter, - DBUS_TYPE_OBJECT_PATH, &path); - free(path); - } - - dbus_message_iter_close_container(&iter, &sub_iter); - -out: - return reply; -} - - -/** - * wpas_dbus_bssid_properties - Return the properties of a scanned network - * @message: Pointer to incoming dbus message - * @wpa_s: wpa_supplicant structure for a network interface - * @res: wpa_supplicant scan result for which to get properties - * Returns: a dbus message containing the properties for the requested network - * - * Handler function for "properties" method call of a scanned network. - * Returns a dbus message containing the the properties. - */ -DBusMessage * wpas_dbus_bssid_properties(DBusMessage *message, - struct wpa_supplicant *wpa_s, - struct wpa_scan_result *res) -{ - DBusMessage *reply = NULL; - char *bssid_data, *ssid_data, *wpa_ie_data, *rsn_ie_data; - DBusMessageIter iter, iter_dict; - - /* dbus needs the address of a pointer to the actual value - * for array types, not the address of the value itself. - */ - bssid_data = (char *) &res->bssid; - ssid_data = (char *) &res->ssid; - wpa_ie_data = (char *) &res->wpa_ie; - rsn_ie_data = (char *) &res->rsn_ie; - - /* Dump the properties into a dbus message */ - reply = dbus_message_new_method_return(message); - - dbus_message_iter_init_append(reply, &iter); - if (!wpa_dbus_dict_open_write(&iter, &iter_dict)) - goto error; - - if (!wpa_dbus_dict_append_byte_array(&iter_dict, "bssid", - bssid_data, ETH_ALEN)) - goto error; - if (!wpa_dbus_dict_append_byte_array(&iter_dict, "ssid", - ssid_data, res->ssid_len)) - goto error; - if (res->wpa_ie_len) { - if (!wpa_dbus_dict_append_byte_array(&iter_dict, "wpaie", - wpa_ie_data, - res->wpa_ie_len)) { - goto error; - } - } - if (res->rsn_ie_len) { - if (!wpa_dbus_dict_append_byte_array(&iter_dict, "rsnie", - rsn_ie_data, - res->rsn_ie_len)) { - goto error; - } - } - if (res->freq) { - if (!wpa_dbus_dict_append_int32(&iter_dict, "frequency", - res->freq)) - goto error; - } - if (!wpa_dbus_dict_append_uint16(&iter_dict, "capabilities", - res->caps)) - goto error; - if (!wpa_dbus_dict_append_int32(&iter_dict, "quality", res->qual)) - goto error; - if (!wpa_dbus_dict_append_int32(&iter_dict, "noise", res->noise)) - goto error; - if (!wpa_dbus_dict_append_int32(&iter_dict, "level", res->level)) - goto error; - if (!wpa_dbus_dict_append_int32(&iter_dict, "maxrate", res->maxrate)) - goto error; - - if (!wpa_dbus_dict_close_write(&iter, &iter_dict)) - goto error; - - return reply; - -error: - if (reply) - dbus_message_unref(reply); - return dbus_message_new_error(message, WPAS_ERROR_INTERNAL_ERROR, - "an internal error occurred returning " - "BSSID properties."); -} - - -/** - * wpas_dbus_iface_capabilities - Return interface capabilities - * @message: Pointer to incoming dbus message - * @wpa_s: wpa_supplicant structure for a network interface - * Returns: A dbus message containing a dict of strings - * - * Handler function for "capabilities" method call of an interface. - */ -DBusMessage * wpas_dbus_iface_capabilities(DBusMessage *message, - struct wpa_supplicant *wpa_s) -{ - DBusMessage *reply = NULL; - struct wpa_driver_capa capa; - int res; - DBusMessageIter iter, iter_dict; - char **eap_methods; - size_t num_items; - dbus_bool_t strict = FALSE; - DBusMessageIter iter_dict_entry, iter_dict_val, iter_array; - - if (!dbus_message_get_args(message, NULL, - DBUS_TYPE_BOOLEAN, &strict, - DBUS_TYPE_INVALID)) - strict = FALSE; - - reply = dbus_message_new_method_return(message); - - dbus_message_iter_init_append(reply, &iter); - if (!wpa_dbus_dict_open_write(&iter, &iter_dict)) - goto error; - - /* EAP methods */ - eap_methods = eap_get_names_as_string_array(&num_items); - if (eap_methods) { - dbus_bool_t success = FALSE; - size_t i = 0; - - success = wpa_dbus_dict_append_string_array( - &iter_dict, "eap", (const char **) eap_methods, - num_items); - - /* free returned method array */ - while (eap_methods[i]) - free(eap_methods[i++]); - free(eap_methods); - - if (!success) - goto error; - } - - res = wpa_drv_get_capa(wpa_s, &capa); - - /***** pairwise cipher */ - if (res < 0) { - if (!strict) { - const char *args[] = {"CCMP", "TKIP", "NONE"}; - if (!wpa_dbus_dict_append_string_array( - &iter_dict, "pairwise", args, - sizeof(args) / sizeof(char*))) - goto error; - } - } else { - if (!wpa_dbus_dict_begin_string_array(&iter_dict, "pairwise", - &iter_dict_entry, - &iter_dict_val, - &iter_array)) - goto error; - - if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) { - if (!wpa_dbus_dict_string_array_add_element( - &iter_array, "CCMP")) - goto error; - } - - if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) { - if (!wpa_dbus_dict_string_array_add_element( - &iter_array, "TKIP")) - goto error; - } - - if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { - if (!wpa_dbus_dict_string_array_add_element( - &iter_array, "NONE")) - goto error; - } - - if (!wpa_dbus_dict_end_string_array(&iter_dict, - &iter_dict_entry, - &iter_dict_val, - &iter_array)) - goto error; - } - - /***** group cipher */ - if (res < 0) { - if (!strict) { - const char *args[] = { - "CCMP", "TKIP", "WEP104", "WEP40" - }; - if (!wpa_dbus_dict_append_string_array( - &iter_dict, "group", args, - sizeof(args) / sizeof(char*))) - goto error; - } - } else { - if (!wpa_dbus_dict_begin_string_array(&iter_dict, "group", - &iter_dict_entry, - &iter_dict_val, - &iter_array)) - goto error; - - if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) { - if (!wpa_dbus_dict_string_array_add_element( - &iter_array, "CCMP")) - goto error; - } - - if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) { - if (!wpa_dbus_dict_string_array_add_element( - &iter_array, "TKIP")) - goto error; - } - - if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) { - if (!wpa_dbus_dict_string_array_add_element( - &iter_array, "WEP104")) - goto error; - } - - if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) { - if (!wpa_dbus_dict_string_array_add_element( - &iter_array, "WEP40")) - goto error; - } - - if (!wpa_dbus_dict_end_string_array(&iter_dict, - &iter_dict_entry, - &iter_dict_val, - &iter_array)) - goto error; - } - - /***** key management */ - if (res < 0) { - if (!strict) { - const char *args[] = { - "WPA-PSK", "WPA-EAP", "IEEE8021X", "WPA-NONE", - "NONE" - }; - if (!wpa_dbus_dict_append_string_array( - &iter_dict, "key_mgmt", args, - sizeof(args) / sizeof(char*))) - goto error; - } - } else { - if (!wpa_dbus_dict_begin_string_array(&iter_dict, "key_mgmt", - &iter_dict_entry, - &iter_dict_val, - &iter_array)) - goto error; - - if (!wpa_dbus_dict_string_array_add_element(&iter_array, - "NONE")) - goto error; - - if (!wpa_dbus_dict_string_array_add_element(&iter_array, - "IEEE8021X")) - goto error; - - if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) { - if (!wpa_dbus_dict_string_array_add_element( - &iter_array, "WPA-EAP")) - goto error; - } - - if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { - if (!wpa_dbus_dict_string_array_add_element( - &iter_array, "WPA-PSK")) - goto error; - } - - if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { - if (!wpa_dbus_dict_string_array_add_element( - &iter_array, "WPA-NONE")) - goto error; - } - - if (!wpa_dbus_dict_end_string_array(&iter_dict, - &iter_dict_entry, - &iter_dict_val, - &iter_array)) - goto error; - } - - /***** WPA protocol */ - if (res < 0) { - if (!strict) { - const char *args[] = { "RSN", "WPA" }; - if (!wpa_dbus_dict_append_string_array( - &iter_dict, "proto", args, - sizeof(args) / sizeof(char*))) - goto error; - } - } else { - if (!wpa_dbus_dict_begin_string_array(&iter_dict, "proto", - &iter_dict_entry, - &iter_dict_val, - &iter_array)) - goto error; - - if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { - if (!wpa_dbus_dict_string_array_add_element( - &iter_array, "RSN")) - goto error; - } - - if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | - WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) { - if (!wpa_dbus_dict_string_array_add_element( - &iter_array, "WPA")) - goto error; - } - - if (!wpa_dbus_dict_end_string_array(&iter_dict, - &iter_dict_entry, - &iter_dict_val, - &iter_array)) - goto error; - } - - /***** auth alg */ - if (res < 0) { - if (!strict) { - const char *args[] = { "OPEN", "SHARED", "LEAP" }; - if (!wpa_dbus_dict_append_string_array( - &iter_dict, "auth_alg", args, - sizeof(args) / sizeof(char*))) - goto error; - } - } else { - if (!wpa_dbus_dict_begin_string_array(&iter_dict, "auth_alg", - &iter_dict_entry, - &iter_dict_val, - &iter_array)) - goto error; - - if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) { - if (!wpa_dbus_dict_string_array_add_element( - &iter_array, "OPEN")) - goto error; - } - - if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) { - if (!wpa_dbus_dict_string_array_add_element( - &iter_array, "SHARED")) - goto error; - } - - if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) { - if (!wpa_dbus_dict_string_array_add_element( - &iter_array, "LEAP")) - goto error; - } - - if (!wpa_dbus_dict_end_string_array(&iter_dict, - &iter_dict_entry, - &iter_dict_val, - &iter_array)) - goto error; - } - - if (!wpa_dbus_dict_close_write(&iter, &iter_dict)) - goto error; - - return reply; - -error: - if (reply) - dbus_message_unref(reply); - return dbus_message_new_error(message, WPAS_ERROR_INTERNAL_ERROR, - "an internal error occurred returning " - "interface capabilities."); -} - - -/** - * wpas_dbus_iface_add_network - Add a new configured network - * @message: Pointer to incoming dbus message - * @wpa_s: wpa_supplicant structure for a network interface - * Returns: A dbus message containing the object path of the new network - * - * Handler function for "addNetwork" method call of a network interface. - */ -DBusMessage * wpas_dbus_iface_add_network(DBusMessage *message, - struct wpa_supplicant *wpa_s) -{ - DBusMessage *reply = NULL; - struct wpa_ssid *ssid; - char *path = NULL; - - path = wpa_zalloc(WPAS_DBUS_OBJECT_PATH_MAX); - if (path == NULL) { - perror("wpas_dbus_iface_scan_results[dbus]: out of " - "memory."); - wpa_printf(MSG_ERROR, "dbus control interface: not " - "enough memory to send scan results " - "signal."); - goto out; - } - - ssid = wpa_config_add_network(wpa_s->conf); - if (ssid == NULL) { - reply = dbus_message_new_error(message, - WPAS_ERROR_ADD_NETWORK_ERROR, - "wpa_supplicant could not add " - "a network on this interface."); - goto out; - } - ssid->disabled = 1; - wpa_config_set_network_defaults(ssid); - - /* Construct the object path for this network. */ - snprintf(path, WPAS_DBUS_OBJECT_PATH_MAX, - "%s/" WPAS_DBUS_NETWORKS_PART "/%d", - wpa_supplicant_get_dbus_path(wpa_s), - ssid->id); - - reply = dbus_message_new_method_return(message); - dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, - &path, DBUS_TYPE_INVALID); - -out: - free(path); - return reply; -} - - -/** - * wpas_dbus_iface_remove_network - Remove a configured network - * @message: Pointer to incoming dbus message - * @wpa_s: wpa_supplicant structure for a network interface - * Returns: A dbus message containing a UINT32 indicating success (1) or - * failure (0) - * - * Handler function for "removeNetwork" method call of a network interface. - */ -DBusMessage * wpas_dbus_iface_remove_network(DBusMessage *message, - struct wpa_supplicant *wpa_s) -{ - DBusMessage *reply = NULL; - const char *op; - char *iface = NULL, *net_id = NULL; - int id; - struct wpa_ssid *ssid; - - if (!dbus_message_get_args(message, NULL, - DBUS_TYPE_OBJECT_PATH, &op, - DBUS_TYPE_INVALID)) { - reply = wpas_dbus_new_invalid_opts_error(message, NULL); - goto out; - } - - /* Extract the network ID */ - iface = wpas_dbus_decompose_object_path(op, &net_id, NULL); - if (iface == NULL) { - reply = wpas_dbus_new_invalid_network_error(message); - goto out; - } - /* Ensure the network is actually a child of this interface */ - if (strcmp(iface, wpa_supplicant_get_dbus_path(wpa_s)) != 0) { - reply = wpas_dbus_new_invalid_network_error(message); - goto out; - } - - id = strtoul(net_id, NULL, 10); - ssid = wpa_config_get_network(wpa_s->conf, id); - if (ssid == NULL) { - reply = wpas_dbus_new_invalid_network_error(message); - goto out; - } - - if (wpa_config_remove_network(wpa_s->conf, id) < 0) { - reply = dbus_message_new_error(message, - WPAS_ERROR_REMOVE_NETWORK_ERROR, - "error removing the specified " - "on this interface."); - goto out; - } - - if (ssid == wpa_s->current_ssid) - wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING); - reply = wpas_dbus_new_success_reply(message); - -out: - free(iface); - free(net_id); - return reply; -} - - -static const char *dont_quote[] = { - "key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap", - "opensc_engine_path", "pkcs11_engine_path", "pkcs11_module_path", - "bssid", NULL -}; - -static dbus_bool_t should_quote_opt(const char *key) -{ - int i = 0; - while (dont_quote[i] != NULL) { - if (strcmp(key, dont_quote[i]) == 0) - return FALSE; - i++; - } - return TRUE; -} - -/** - * wpas_dbus_iface_set_network - Set options for a configured network - * @message: Pointer to incoming dbus message - * @wpa_s: wpa_supplicant structure for a network interface - * @ssid: wpa_ssid structure for a configured network - * Returns: a dbus message containing a UINT32 indicating success (1) or - * failure (0) - * - * Handler function for "set" method call of a configured network. - */ -DBusMessage * wpas_dbus_iface_set_network(DBusMessage *message, - struct wpa_supplicant *wpa_s, - struct wpa_ssid *ssid) -{ - DBusMessage *reply = NULL; - struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING }; - DBusMessageIter iter, iter_dict; - - dbus_message_iter_init(message, &iter); - - if (!wpa_dbus_dict_open_read(&iter, &iter_dict)) { - reply = wpas_dbus_new_invalid_opts_error(message, NULL); - goto out; - } - - while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { - char *value = NULL; - size_t size = 50; - int ret; - - if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) { - reply = wpas_dbus_new_invalid_opts_error(message, - NULL); - goto out; - } - - /* Type conversions, since wpa_supplicant wants strings */ - if (entry.type == DBUS_TYPE_ARRAY && - entry.array_type == DBUS_TYPE_BYTE) { - if (entry.array_len <= 0) - goto error; - - size = entry.array_len * 2 + 1; - value = wpa_zalloc(size); - if (value == NULL) - goto error; - ret = wpa_snprintf_hex(value, size, - (u8 *) entry.bytearray_value, - entry.array_len); - if (ret <= 0) - goto error; - } else if (entry.type == DBUS_TYPE_STRING) { - if (should_quote_opt(entry.key)) { - size = strlen(entry.str_value); - /* Zero-length option check */ - if (size <= 0) - goto error; - size += 3; /* For quotes and terminator */ - value = wpa_zalloc(size); - if (value == NULL) - goto error; - ret = snprintf(value, size, "\"%s\"", - entry.str_value); - if (ret < 0 || (size_t) ret != (size - 1)) - goto error; - } else { - value = strdup(entry.str_value); - if (value == NULL) - goto error; - } - } else if (entry.type == DBUS_TYPE_UINT32) { - value = wpa_zalloc(size); - if (value == NULL) - goto error; - ret = snprintf(value, size, "%u", entry.uint32_value); - if (ret <= 0) - goto error; - } else if (entry.type == DBUS_TYPE_INT32) { - value = wpa_zalloc(size); - if (value == NULL) - goto error; - ret = snprintf(value, size, "%d", entry.int32_value); - if (ret <= 0) - goto error; - } else - goto error; - - if (wpa_config_set(ssid, entry.key, value, 0) < 0) - goto error; - - if ((strcmp(entry.key, "psk") == 0 && - value[0] == '"' && ssid->ssid_len) || - (strcmp(entry.key, "ssid") == 0 && ssid->passphrase)) - wpa_config_update_psk(ssid); - - free(value); - wpa_dbus_dict_entry_clear(&entry); - continue; - - error: - free(value); - reply = wpas_dbus_new_invalid_opts_error(message, entry.key); - wpa_dbus_dict_entry_clear(&entry); - break; - } - - if (!reply) - reply = wpas_dbus_new_success_reply(message); - -out: - return reply; -} - - -/** - * wpas_dbus_iface_enable_network - Mark a configured network as enabled - * @message: Pointer to incoming dbus message - * @wpa_s: wpa_supplicant structure for a network interface - * @ssid: wpa_ssid structure for a configured network - * Returns: A dbus message containing a UINT32 indicating success (1) or - * failure (0) - * - * Handler function for "enable" method call of a configured network. - */ -DBusMessage * wpas_dbus_iface_enable_network(DBusMessage *message, - struct wpa_supplicant *wpa_s, - struct wpa_ssid *ssid) -{ - if (wpa_s->current_ssid == NULL && ssid->disabled) { - /* - * Try to reassociate since there is no current configuration - * and a new network was made available. - */ - wpa_s->reassociate = 1; - wpa_supplicant_req_scan(wpa_s, 0, 0); - } - ssid->disabled = 0; - - return wpas_dbus_new_success_reply(message); -} - - -/** - * wpas_dbus_iface_disable_network - Mark a configured network as disabled - * @message: Pointer to incoming dbus message - * @wpa_s: wpa_supplicant structure for a network interface - * @ssid: wpa_ssid structure for a configured network - * Returns: A dbus message containing a UINT32 indicating success (1) or - * failure (0) - * - * Handler function for "disable" method call of a configured network. - */ -DBusMessage * wpas_dbus_iface_disable_network(DBusMessage *message, - struct wpa_supplicant *wpa_s, - struct wpa_ssid *ssid) -{ - if (ssid == wpa_s->current_ssid) - wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING); - ssid->disabled = 1; - - return wpas_dbus_new_success_reply(message); -} - - -/** - * wpas_dbus_iface_select_network - Attempt association with a configured network - * @message: Pointer to incoming dbus message - * @wpa_s: wpa_supplicant structure for a network interface - * Returns: A dbus message containing a UINT32 indicating success (1) or - * failure (0) - * - * Handler function for "selectNetwork" method call of network interface. - */ -DBusMessage * wpas_dbus_iface_select_network(DBusMessage *message, - struct wpa_supplicant *wpa_s) -{ - DBusMessage *reply = NULL; - const char *op; - struct wpa_ssid *ssid; - char *iface_obj_path = NULL; - char *network = NULL; - - if (strlen(dbus_message_get_signature(message)) == 0) { - /* Any network */ - ssid = wpa_s->conf->ssid; - while (ssid) { - ssid->disabled = 0; - ssid = ssid->next; - } - wpa_s->reassociate = 1; - wpa_supplicant_req_scan(wpa_s, 0, 0); - } else { - const char *obj_path; - int nid; - - if (!dbus_message_get_args(message, NULL, - DBUS_TYPE_OBJECT_PATH, &op, - DBUS_TYPE_INVALID)) { - reply = wpas_dbus_new_invalid_opts_error(message, - NULL); - goto out; - } - - /* Extract the network number */ - iface_obj_path = wpas_dbus_decompose_object_path(op, - &network, - NULL); - if (iface_obj_path == NULL) { - reply = wpas_dbus_new_invalid_iface_error(message); - goto out; - } - /* Ensure the object path really points to this interface */ - obj_path = wpa_supplicant_get_dbus_path(wpa_s); - if (strcmp(iface_obj_path, obj_path) != 0) { - reply = wpas_dbus_new_invalid_network_error(message); - goto out; - } - - nid = strtoul(network, NULL, 10); - if (errno == EINVAL) { - reply = wpas_dbus_new_invalid_network_error(message); - goto out; - } - - ssid = wpa_config_get_network(wpa_s->conf, nid); - if (ssid == NULL) { - reply = wpas_dbus_new_invalid_network_error(message); - goto out; - } - - /* Finally, associate with the network */ - if (ssid != wpa_s->current_ssid && wpa_s->current_ssid) - wpa_supplicant_disassociate(wpa_s, - REASON_DEAUTH_LEAVING); - - /* Mark all other networks disabled and trigger reassociation - */ - ssid = wpa_s->conf->ssid; - while (ssid) { - ssid->disabled = (nid != ssid->id); - ssid = ssid->next; - } - wpa_s->disconnected = 0; - wpa_s->reassociate = 1; - wpa_supplicant_req_scan(wpa_s, 0, 0); - } - - reply = wpas_dbus_new_success_reply(message); - -out: - free(iface_obj_path); - free(network); - return reply; -} - - -/** - * wpas_dbus_iface_disconnect - Terminate the current connection - * @message: Pointer to incoming dbus message - * @wpa_s: wpa_supplicant structure for a network interface - * Returns: A dbus message containing a UINT32 indicating success (1) or - * failure (0) - * - * Handler function for "disconnect" method call of network interface. - */ -DBusMessage * wpas_dbus_iface_disconnect(DBusMessage *message, - struct wpa_supplicant *wpa_s) -{ - wpa_s->disconnected = 1; - wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING); - - return wpas_dbus_new_success_reply(message); -} - - -/** - * wpas_dbus_iface_set_ap_scan - Control roaming mode - * @message: Pointer to incoming dbus message - * @wpa_s: wpa_supplicant structure for a network interface - * Returns: A dbus message containing a UINT32 indicating success (1) or - * failure (0) - * - * Handler function for "setAPScan" method call. - */ -DBusMessage * wpas_dbus_iface_set_ap_scan(DBusMessage *message, - struct wpa_supplicant *wpa_s) -{ - DBusMessage *reply = NULL; - dbus_uint32_t ap_scan = 1; - - if (!dbus_message_get_args(message, NULL, DBUS_TYPE_UINT32, &ap_scan, - DBUS_TYPE_INVALID)) { - reply = wpas_dbus_new_invalid_opts_error(message, NULL); - goto out; - } - - if (ap_scan > 2) { - reply = wpas_dbus_new_invalid_opts_error(message, NULL); - goto out; - } - wpa_s->conf->ap_scan = ap_scan; - reply = wpas_dbus_new_success_reply(message); - -out: - return reply; -} - - -/** - * wpas_dbus_iface_get_state - Get interface state - * @message: Pointer to incoming dbus message - * @wpa_s: wpa_supplicant structure for a network interface - * Returns: A dbus message containing a STRING representing the current - * interface state - * - * Handler function for "state" method call. - */ -DBusMessage * wpas_dbus_iface_get_state(DBusMessage *message, - struct wpa_supplicant *wpa_s) -{ - DBusMessage *reply = NULL; - const char *str_state; - - reply = dbus_message_new_method_return(message); - if (reply != NULL) { - str_state = wpa_supplicant_state_txt(wpa_s->wpa_state); - dbus_message_append_args(reply, DBUS_TYPE_STRING, &str_state, - DBUS_TYPE_INVALID); - } - - return reply; -} - - -/** - * wpas_dbus_iface_set_blobs - Store named binary blobs (ie, for certificates) - * @message: Pointer to incoming dbus message - * @global: %wpa_supplicant global data structure - * Returns: A dbus message containing a UINT32 indicating success (1) or - * failure (0) - * - * Asks wpa_supplicant to internally store a one or more binary blobs. - */ -DBusMessage * wpas_dbus_iface_set_blobs(DBusMessage *message, - struct wpa_supplicant *wpa_s) -{ - DBusMessage *reply = NULL; - struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING }; - DBusMessageIter iter, iter_dict; - - dbus_message_iter_init(message, &iter); - - if (!wpa_dbus_dict_open_read(&iter, &iter_dict)) - return wpas_dbus_new_invalid_opts_error(message, NULL); - - while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { - struct wpa_config_blob *blob; - - if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) { - reply = wpas_dbus_new_invalid_opts_error(message, - NULL); - break; - } - - if (entry.type != DBUS_TYPE_ARRAY || - entry.array_type != DBUS_TYPE_BYTE) { - reply = wpas_dbus_new_invalid_opts_error( - message, "Byte array expected."); - break; - } - - if ((entry.array_len <= 0) || (entry.array_len > 65536) || - !strlen(entry.key)) { - reply = wpas_dbus_new_invalid_opts_error( - message, "Invalid array size."); - break; - } - - blob = os_zalloc(sizeof(*blob)); - if (blob == NULL) { - reply = dbus_message_new_error( - message, WPAS_ERROR_ADD_ERROR, - "Not enough memory to add blob."); - break; - } - blob->data = os_zalloc(entry.array_len); - if (blob->data == NULL) { - reply = dbus_message_new_error( - message, WPAS_ERROR_ADD_ERROR, - "Not enough memory to add blob data."); - os_free(blob); - break; - } - - blob->name = os_strdup(entry.key); - blob->len = entry.array_len; - os_memcpy(blob->data, (u8 *) entry.bytearray_value, - entry.array_len); - if (blob->name == NULL || blob->data == NULL) { - wpa_config_free_blob(blob); - reply = dbus_message_new_error( - message, WPAS_ERROR_ADD_ERROR, - "Error adding blob."); - break; - } - - /* Success */ - wpa_config_remove_blob(wpa_s->conf, blob->name); - wpa_config_set_blob(wpa_s->conf, blob); - wpa_dbus_dict_entry_clear(&entry); - } - wpa_dbus_dict_entry_clear(&entry); - - return reply ? reply : wpas_dbus_new_success_reply(message); -} - - -/** - * wpas_dbus_iface_remove_blob - Remove named binary blobs - * @message: Pointer to incoming dbus message - * @global: %wpa_supplicant global data structure - * Returns: A dbus message containing a UINT32 indicating success (1) or - * failure (0) - * - * Asks wpa_supplicant to remove one or more previously stored binary blobs. - */ -DBusMessage * wpas_dbus_iface_remove_blobs(DBusMessage *message, - struct wpa_supplicant *wpa_s) -{ - DBusMessageIter iter, array; - char *err_msg = NULL; - - dbus_message_iter_init(message, &iter); - - if ((dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY) || - (dbus_message_iter_get_element_type (&iter) != DBUS_TYPE_STRING)) - return wpas_dbus_new_invalid_opts_error(message, NULL); - - dbus_message_iter_recurse(&iter, &array); - while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRING) { - const char *name; - - dbus_message_iter_get_basic(&array, &name); - if (!strlen(name)) - err_msg = "Invalid blob name."; - - if (wpa_config_remove_blob(wpa_s->conf, name) != 0) - err_msg = "Error removing blob."; - dbus_message_iter_next(&array); - } - - if (err_msg) { - return dbus_message_new_error(message, WPAS_ERROR_REMOVE_ERROR, - err_msg); - } - - return wpas_dbus_new_success_reply(message); -} diff --git a/contrib/wpa_supplicant/ctrl_iface_dbus_handlers.h b/contrib/wpa_supplicant/ctrl_iface_dbus_handlers.h deleted file mode 100644 index 0ae94c41b7ce..000000000000 --- a/contrib/wpa_supplicant/ctrl_iface_dbus_handlers.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * WPA Supplicant / dbus-based control interface - * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, 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 CTRL_IFACE_DBUS_HANDLERS_H -#define CTRL_IFACE_DBUS_HANDLERS_H - -#ifdef CONFIG_CTRL_IFACE_DBUS - -DBusMessage * wpas_dbus_new_invalid_iface_error(DBusMessage *message); - -DBusMessage * wpas_dbus_global_add_interface(DBusMessage *message, - struct wpa_global *global); - -DBusMessage * wpas_dbus_global_remove_interface(DBusMessage *message, - struct wpa_global *global); - -DBusMessage * wpas_dbus_global_get_interface(DBusMessage *message, - struct wpa_global *global); - -DBusMessage * wpas_dbus_iface_scan(DBusMessage *message, - struct wpa_supplicant *wpa_s); - -DBusMessage * wpas_dbus_iface_scan_results(DBusMessage *message, - struct wpa_supplicant *wpa_s); - -DBusMessage * wpas_dbus_bssid_properties(DBusMessage *message, - struct wpa_supplicant *wpa_s, - struct wpa_scan_result *res); - -DBusMessage * wpas_dbus_iface_capabilities(DBusMessage *message, - struct wpa_supplicant *wpa_s); - -DBusMessage * wpas_dbus_iface_add_network(DBusMessage *message, - struct wpa_supplicant *wpa_s); - -DBusMessage * wpas_dbus_iface_remove_network(DBusMessage *message, - struct wpa_supplicant *wpa_s); - -DBusMessage * wpas_dbus_iface_set_network(DBusMessage *message, - struct wpa_supplicant *wpa_s, - struct wpa_ssid *ssid); - -DBusMessage * wpas_dbus_iface_enable_network(DBusMessage *message, - struct wpa_supplicant *wpa_s, - struct wpa_ssid *ssid); - -DBusMessage * wpas_dbus_iface_disable_network(DBusMessage *message, - struct wpa_supplicant *wpa_s, - struct wpa_ssid *ssid); - -DBusMessage * wpas_dbus_iface_select_network(DBusMessage *message, - struct wpa_supplicant *wpa_s); - -DBusMessage * wpas_dbus_iface_disconnect(DBusMessage *message, - struct wpa_supplicant *wpa_s); - -DBusMessage * wpas_dbus_iface_set_ap_scan(DBusMessage *message, - struct wpa_supplicant *wpa_s); - -DBusMessage * wpas_dbus_iface_get_state(DBusMessage *message, - struct wpa_supplicant *wpa_s); - -DBusMessage * wpas_dbus_iface_set_blobs(DBusMessage *message, - struct wpa_supplicant *wpa_s); - -DBusMessage * wpas_dbus_iface_remove_blobs(DBusMessage *message, - struct wpa_supplicant *wpa_s); - -#endif /* CONFIG_CTRL_IFACE_DBUS */ - -#endif /* CTRL_IFACE_DBUS_HANDLERS_H */ - diff --git a/contrib/wpa_supplicant/ctrl_iface_udp.c b/contrib/wpa_supplicant/ctrl_iface_udp.c deleted file mode 100644 index bb6f11d50c9c..000000000000 --- a/contrib/wpa_supplicant/ctrl_iface_udp.c +++ /dev/null @@ -1,561 +0,0 @@ -/* - * WPA Supplicant / UDP socket -based control interface - * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "config.h" -#include "eapol_sm.h" -#include "wpa_supplicant_i.h" -#include "ctrl_iface.h" -#include "wpa_ctrl.h" - - -#define COOKIE_LEN 8 - -/* Per-interface ctrl_iface */ - -/** - * struct wpa_ctrl_dst - Internal data structure of control interface monitors - * - * This structure is used to store information about registered control - * interface monitors into struct wpa_supplicant. This data is private to - * ctrl_iface_udp.c and should not be touched directly from other files. - */ -struct wpa_ctrl_dst { - struct wpa_ctrl_dst *next; - struct sockaddr_in addr; - socklen_t addrlen; - int debug_level; - int errors; -}; - - -struct ctrl_iface_priv { - struct wpa_supplicant *wpa_s; - int sock; - struct wpa_ctrl_dst *ctrl_dst; - u8 cookie[COOKIE_LEN]; -}; - - -static void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv, - int level, const char *buf, - size_t len); - - -static int wpa_supplicant_ctrl_iface_attach(struct ctrl_iface_priv *priv, - struct sockaddr_in *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_in)); - dst->addrlen = fromlen; - dst->debug_level = MSG_INFO; - dst->next = priv->ctrl_dst; - priv->ctrl_dst = dst; - wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor attached %s:%d", - inet_ntoa(from->sin_addr), ntohs(from->sin_port)); - return 0; -} - - -static int wpa_supplicant_ctrl_iface_detach(struct ctrl_iface_priv *priv, - struct sockaddr_in *from, - socklen_t fromlen) -{ - struct wpa_ctrl_dst *dst, *prev = NULL; - - dst = priv->ctrl_dst; - while (dst) { - if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr && - from->sin_port == dst->addr.sin_port) { - if (prev == NULL) - priv->ctrl_dst = dst->next; - else - prev->next = dst->next; - os_free(dst); - wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor detached " - "%s:%d", inet_ntoa(from->sin_addr), - ntohs(from->sin_port)); - return 0; - } - prev = dst; - dst = dst->next; - } - return -1; -} - - -static int wpa_supplicant_ctrl_iface_level(struct ctrl_iface_priv *priv, - struct sockaddr_in *from, - socklen_t fromlen, - char *level) -{ - struct wpa_ctrl_dst *dst; - - wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level); - - dst = priv->ctrl_dst; - while (dst) { - if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr && - from->sin_port == dst->addr.sin_port) { - wpa_printf(MSG_DEBUG, "CTRL_IFACE changed monitor " - "level %s:%d", inet_ntoa(from->sin_addr), - ntohs(from->sin_port)); - dst->debug_level = atoi(level); - return 0; - } - dst = dst->next; - } - - return -1; -} - - -static char * -wpa_supplicant_ctrl_iface_get_cookie(struct ctrl_iface_priv *priv, - size_t *reply_len) -{ - char *reply; - reply = os_malloc(7 + 2 * COOKIE_LEN + 1); - if (reply == NULL) { - *reply_len = 1; - return NULL; - } - - os_memcpy(reply, "COOKIE=", 7); - wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1, - priv->cookie, COOKIE_LEN); - - *reply_len = 7 + 2 * COOKIE_LEN; - return reply; -} - - -static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, - void *sock_ctx) -{ - struct wpa_supplicant *wpa_s = eloop_ctx; - struct ctrl_iface_priv *priv = sock_ctx; - char buf[256], *pos; - int res; - struct sockaddr_in from; - socklen_t fromlen = sizeof(from); - char *reply = NULL; - size_t reply_len = 0; - int new_attached = 0; - u8 cookie[COOKIE_LEN]; - - res = recvfrom(sock, buf, sizeof(buf) - 1, 0, - (struct sockaddr *) &from, &fromlen); - if (res < 0) { - perror("recvfrom(ctrl_iface)"); - return; - } - if (from.sin_addr.s_addr != htonl((127 << 24) | 1)) { - /* - * The OS networking stack is expected to drop this kind of - * frames since the socket is bound to only localhost address. - * Just in case, drop the frame if it is coming from any other - * address. - */ - wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected " - "source %s", inet_ntoa(from.sin_addr)); - return; - } - buf[res] = '\0'; - - if (os_strcmp(buf, "GET_COOKIE") == 0) { - reply = wpa_supplicant_ctrl_iface_get_cookie(priv, &reply_len); - goto done; - } - - /* - * Require that the client includes a prefix with the 'cookie' value - * fetched with GET_COOKIE command. This is used to verify that the - * client has access to a bidirectional link over UDP in order to - * avoid attacks using forged localhost IP address even if the OS does - * not block such frames from remote destinations. - */ - if (os_strncmp(buf, "COOKIE=", 7) != 0) { - wpa_printf(MSG_DEBUG, "CTLR: No cookie in the request - " - "drop request"); - return; - } - - if (hexstr2bin(buf + 7, cookie, COOKIE_LEN) < 0) { - wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie format in the " - "request - drop request"); - return; - } - - if (os_memcmp(cookie, priv->cookie, COOKIE_LEN) != 0) { - wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request - " - "drop request"); - return; - } - - pos = buf + 7 + 2 * COOKIE_LEN; - while (*pos == ' ') - pos++; - - if (os_strcmp(pos, "ATTACH") == 0) { - if (wpa_supplicant_ctrl_iface_attach(priv, &from, fromlen)) - reply_len = 1; - else { - new_attached = 1; - reply_len = 2; - } - } else if (os_strcmp(pos, "DETACH") == 0) { - if (wpa_supplicant_ctrl_iface_detach(priv, &from, fromlen)) - reply_len = 1; - else - reply_len = 2; - } else if (os_strncmp(pos, "LEVEL ", 6) == 0) { - if (wpa_supplicant_ctrl_iface_level(priv, &from, fromlen, - pos + 6)) - reply_len = 1; - else - reply_len = 2; - } else { - reply = wpa_supplicant_ctrl_iface_process(wpa_s, pos, - &reply_len); - } - - done: - if (reply) { - sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, - fromlen); - os_free(reply); - } else if (reply_len == 1) { - sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, - fromlen); - } else if (reply_len == 2) { - sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from, - fromlen); - } - - if (new_attached) - eapol_sm_notify_ctrl_attached(wpa_s->eapol); -} - - -static void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level, - const char *txt, size_t len) -{ - struct wpa_supplicant *wpa_s = ctx; - if (wpa_s == NULL || wpa_s->ctrl_iface == NULL) - return; - wpa_supplicant_ctrl_iface_send(wpa_s->ctrl_iface, level, txt, len); -} - - -struct ctrl_iface_priv * -wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s) -{ - struct ctrl_iface_priv *priv; - struct sockaddr_in addr; - - priv = os_zalloc(sizeof(*priv)); - if (priv == NULL) - return NULL; - priv->wpa_s = wpa_s; - priv->sock = -1; - os_get_random(priv->cookie, COOKIE_LEN); - - if (wpa_s->conf->ctrl_interface == NULL) - return priv; - - priv->sock = socket(PF_INET, SOCK_DGRAM, 0); - if (priv->sock < 0) { - perror("socket(PF_INET)"); - goto fail; - } - - os_memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl((127 << 24) | 1); - addr.sin_port = htons(WPA_CTRL_IFACE_PORT); - if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror("bind(AF_INET)"); - goto fail; - } - - eloop_register_read_sock(priv->sock, wpa_supplicant_ctrl_iface_receive, - wpa_s, priv); - wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb); - - return priv; - -fail: - if (priv->sock >= 0) - close(priv->sock); - os_free(priv); - return NULL; -} - - -void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv) -{ - struct wpa_ctrl_dst *dst, *prev; - - if (priv->sock > -1) { - eloop_unregister_read_sock(priv->sock); - if (priv->ctrl_dst) { - /* - * Wait a second before closing the control socket if - * there are any attached monitors in order to allow - * them to receive any pending messages. - */ - wpa_printf(MSG_DEBUG, "CTRL_IFACE wait for attached " - "monitors to receive messages"); - os_sleep(1, 0); - } - close(priv->sock); - priv->sock = -1; - } - - dst = priv->ctrl_dst; - while (dst) { - prev = dst; - dst = dst->next; - os_free(prev); - } - os_free(priv); -} - - -static void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv, - int level, const char *buf, - size_t len) -{ - struct wpa_ctrl_dst *dst, *next; - char levelstr[10]; - int idx; - char *sbuf; - int llen; - - dst = priv->ctrl_dst; - if (priv->sock < 0 || dst == NULL) - return; - - os_snprintf(levelstr, sizeof(levelstr), "<%d>", level); - - llen = os_strlen(levelstr); - sbuf = os_malloc(llen + len); - if (sbuf == NULL) - return; - - os_memcpy(sbuf, levelstr, llen); - os_memcpy(sbuf + llen, buf, len); - - idx = 0; - while (dst) { - next = dst->next; - if (level >= dst->debug_level) { - wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor send %s:%d", - inet_ntoa(dst->addr.sin_addr), - ntohs(dst->addr.sin_port)); - if (sendto(priv->sock, sbuf, llen + len, 0, - (struct sockaddr *) &dst->addr, - sizeof(dst->addr)) < 0) { - perror("sendto(CTRL_IFACE monitor)"); - dst->errors++; - if (dst->errors > 10) { - wpa_supplicant_ctrl_iface_detach( - priv, &dst->addr, - dst->addrlen); - } - } else - dst->errors = 0; - } - idx++; - dst = next; - } - os_free(sbuf); -} - - -void wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv) -{ - wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor", - priv->wpa_s->ifname); - eloop_wait_for_read_sock(priv->sock); -} - - -/* Global ctrl_iface */ - -struct ctrl_iface_global_priv { - int sock; - u8 cookie[COOKIE_LEN]; -}; - - -static char * -wpa_supplicant_global_get_cookie(struct ctrl_iface_global_priv *priv, - size_t *reply_len) -{ - char *reply; - reply = os_malloc(7 + 2 * COOKIE_LEN + 1); - if (reply == NULL) { - *reply_len = 1; - return NULL; - } - - os_memcpy(reply, "COOKIE=", 7); - wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1, - priv->cookie, COOKIE_LEN); - - *reply_len = 7 + 2 * COOKIE_LEN; - return reply; -} - - -static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, - void *sock_ctx) -{ - struct wpa_global *global = eloop_ctx; - struct ctrl_iface_global_priv *priv = sock_ctx; - char buf[256], *pos; - int res; - struct sockaddr_in from; - socklen_t fromlen = sizeof(from); - char *reply; - size_t reply_len; - u8 cookie[COOKIE_LEN]; - - res = recvfrom(sock, buf, sizeof(buf) - 1, 0, - (struct sockaddr *) &from, &fromlen); - if (res < 0) { - perror("recvfrom(ctrl_iface)"); - return; - } - if (from.sin_addr.s_addr != htonl((127 << 24) | 1)) { - /* - * The OS networking stack is expected to drop this kind of - * frames since the socket is bound to only localhost address. - * Just in case, drop the frame if it is coming from any other - * address. - */ - wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected " - "source %s", inet_ntoa(from.sin_addr)); - return; - } - buf[res] = '\0'; - - if (os_strcmp(buf, "GET_COOKIE") == 0) { - reply = wpa_supplicant_global_get_cookie(priv, &reply_len); - goto done; - } - - if (os_strncmp(buf, "COOKIE=", 7) != 0) { - wpa_printf(MSG_DEBUG, "CTLR: No cookie in the request - " - "drop request"); - return; - } - - if (hexstr2bin(buf + 7, cookie, COOKIE_LEN) < 0) { - wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie format in the " - "request - drop request"); - return; - } - - if (os_memcmp(cookie, priv->cookie, COOKIE_LEN) != 0) { - wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request - " - "drop request"); - return; - } - - pos = buf + 7 + 2 * COOKIE_LEN; - while (*pos == ' ') - pos++; - - reply = wpa_supplicant_global_ctrl_iface_process(global, pos, - &reply_len); - - done: - if (reply) { - sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, - fromlen); - os_free(reply); - } else if (reply_len) { - sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, - fromlen); - } -} - - -struct ctrl_iface_global_priv * -wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global) -{ - struct ctrl_iface_global_priv *priv; - struct sockaddr_in addr; - - priv = os_zalloc(sizeof(*priv)); - if (priv == NULL) - return NULL; - priv->sock = -1; - os_get_random(priv->cookie, COOKIE_LEN); - - if (global->params.ctrl_interface == NULL) - return priv; - - wpa_printf(MSG_DEBUG, "Global control interface '%s'", - global->params.ctrl_interface); - - priv->sock = socket(PF_INET, SOCK_DGRAM, 0); - if (priv->sock < 0) { - perror("socket(PF_INET)"); - goto fail; - } - - os_memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl((127 << 24) | 1); - addr.sin_port = htons(WPA_GLOBAL_CTRL_IFACE_PORT); - if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror("bind(AF_INET)"); - goto fail; - } - - eloop_register_read_sock(priv->sock, - wpa_supplicant_global_ctrl_iface_receive, - global, priv); - - return priv; - -fail: - if (priv->sock >= 0) - close(priv->sock); - os_free(priv); - return NULL; -} - - -void -wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv) -{ - if (priv->sock >= 0) { - eloop_unregister_read_sock(priv->sock); - close(priv->sock); - } - os_free(priv); -} diff --git a/contrib/wpa_supplicant/ctrl_iface_unix.c b/contrib/wpa_supplicant/ctrl_iface_unix.c deleted file mode 100644 index 6c03d464e6b3..000000000000 --- a/contrib/wpa_supplicant/ctrl_iface_unix.c +++ /dev/null @@ -1,689 +0,0 @@ -/* - * WPA Supplicant / UNIX domain socket -based control interface - * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 <sys/un.h> -#include <sys/stat.h> -#include <grp.h> - -#include "common.h" -#include "eloop.h" -#include "config.h" -#include "eapol_sm.h" -#include "wpa_supplicant_i.h" -#include "ctrl_iface.h" - -/* Per-interface ctrl_iface */ - -/** - * struct wpa_ctrl_dst - Internal data structure of control interface monitors - * - * This structure is used to store information about registered control - * interface monitors into struct wpa_supplicant. This data is private to - * ctrl_iface_unix.c and should not be touched directly from other files. - */ -struct wpa_ctrl_dst { - struct wpa_ctrl_dst *next; - struct sockaddr_un addr; - socklen_t addrlen; - int debug_level; - int errors; -}; - - -struct ctrl_iface_priv { - struct wpa_supplicant *wpa_s; - int sock; - struct wpa_ctrl_dst *ctrl_dst; -}; - - -static void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv, - int level, const char *buf, - size_t len); - - -static int wpa_supplicant_ctrl_iface_attach(struct ctrl_iface_priv *priv, - 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 = priv->ctrl_dst; - priv->ctrl_dst = dst; - wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached", - (u8 *) from->sun_path, fromlen - sizeof(from->sun_family)); - return 0; -} - - -static int wpa_supplicant_ctrl_iface_detach(struct ctrl_iface_priv *priv, - struct sockaddr_un *from, - socklen_t fromlen) -{ - struct wpa_ctrl_dst *dst, *prev = NULL; - - dst = priv->ctrl_dst; - while (dst) { - if (fromlen == dst->addrlen && - os_memcmp(from->sun_path, dst->addr.sun_path, - fromlen - sizeof(from->sun_family)) == 0) { - if (prev == NULL) - priv->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 - sizeof(from->sun_family)); - return 0; - } - prev = dst; - dst = dst->next; - } - return -1; -} - - -static int wpa_supplicant_ctrl_iface_level(struct ctrl_iface_priv *priv, - struct sockaddr_un *from, - socklen_t fromlen, - char *level) -{ - struct wpa_ctrl_dst *dst; - - wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level); - - dst = priv->ctrl_dst; - while (dst) { - if (fromlen == dst->addrlen && - os_memcmp(from->sun_path, dst->addr.sun_path, - fromlen - sizeof(from->sun_family)) == 0) { - wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor " - "level", (u8 *) from->sun_path, - fromlen - sizeof(from->sun_family)); - dst->debug_level = atoi(level); - return 0; - } - dst = dst->next; - } - - return -1; -} - - -static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, - void *sock_ctx) -{ - struct wpa_supplicant *wpa_s = eloop_ctx; - struct ctrl_iface_priv *priv = sock_ctx; - char buf[256]; - int res; - struct sockaddr_un from; - socklen_t fromlen = sizeof(from); - char *reply = NULL; - size_t reply_len = 0; - int new_attached = 0; - - 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, "ATTACH") == 0) { - if (wpa_supplicant_ctrl_iface_attach(priv, &from, fromlen)) - reply_len = 1; - else { - new_attached = 1; - reply_len = 2; - } - } else if (os_strcmp(buf, "DETACH") == 0) { - if (wpa_supplicant_ctrl_iface_detach(priv, &from, fromlen)) - reply_len = 1; - else - reply_len = 2; - } else if (os_strncmp(buf, "LEVEL ", 6) == 0) { - if (wpa_supplicant_ctrl_iface_level(priv, &from, fromlen, - buf + 6)) - reply_len = 1; - else - reply_len = 2; - } else { - reply = wpa_supplicant_ctrl_iface_process(wpa_s, buf, - &reply_len); - } - - if (reply) { - sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, - fromlen); - os_free(reply); - } else if (reply_len == 1) { - sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, - fromlen); - } else if (reply_len == 2) { - sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from, - fromlen); - } - - if (new_attached) - eapol_sm_notify_ctrl_attached(wpa_s->eapol); -} - - -static char * wpa_supplicant_ctrl_iface_path(struct wpa_supplicant *wpa_s) -{ - char *buf; - size_t len; - char *pbuf, *dir = NULL, *gid_str = NULL; - - if (wpa_s->conf->ctrl_interface == NULL) - return NULL; - - pbuf = os_strdup(wpa_s->conf->ctrl_interface); - if (pbuf == NULL) - return NULL; - if (os_strncmp(pbuf, "DIR=", 4) == 0) { - dir = pbuf + 4; - gid_str = os_strstr(dir, " GROUP="); - if (gid_str) { - *gid_str = '\0'; - gid_str += 7; - } - } else - dir = pbuf; - - len = os_strlen(dir) + os_strlen(wpa_s->ifname) + 2; - buf = os_malloc(len); - if (buf == NULL) { - os_free(pbuf); - return NULL; - } - - os_snprintf(buf, len, "%s/%s", dir, wpa_s->ifname); -#ifdef __CYGWIN__ - { - /* Windows/WinPcap uses interface names that are not suitable - * as a file name - convert invalid chars to underscores */ - char *pos = buf; - while (*pos) { - if (*pos == '\\') - *pos = '_'; - pos++; - } - } -#endif /* __CYGWIN__ */ - os_free(pbuf); - return buf; -} - - -static void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level, - const char *txt, size_t len) -{ - struct wpa_supplicant *wpa_s = ctx; - if (wpa_s == NULL || wpa_s->ctrl_iface == NULL) - return; - wpa_supplicant_ctrl_iface_send(wpa_s->ctrl_iface, level, txt, len); -} - - -struct ctrl_iface_priv * -wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s) -{ - struct ctrl_iface_priv *priv; - struct sockaddr_un addr; - char *fname = NULL; - gid_t gid = 0; - int gid_set = 0; - char *buf, *dir = NULL, *gid_str = NULL; - struct group *grp; - char *endp; - - priv = os_zalloc(sizeof(*priv)); - if (priv == NULL) - return NULL; - priv->wpa_s = wpa_s; - priv->sock = -1; - - if (wpa_s->conf->ctrl_interface == NULL) - return priv; - - buf = os_strdup(wpa_s->conf->ctrl_interface); - if (buf == NULL) - goto fail; - if (os_strncmp(buf, "DIR=", 4) == 0) { - dir = buf + 4; - gid_str = os_strstr(dir, " GROUP="); - if (gid_str) { - *gid_str = '\0'; - gid_str += 7; - } - } else { - dir = buf; - gid_str = wpa_s->conf->ctrl_interface_group; - } - - if (mkdir(dir, 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 (gid_str) { - grp = getgrnam(gid_str); - if (grp) { - gid = grp->gr_gid; - gid_set = 1; - wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d" - " (from group name '%s')", - (int) gid, gid_str); - } else { - /* Group name not found - try to parse this as gid */ - gid = strtol(gid_str, &endp, 10); - if (*gid_str == '\0' || *endp != '\0') { - wpa_printf(MSG_ERROR, "CTRL: Invalid group " - "'%s'", gid_str); - goto fail; - } - gid_set = 1; - wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d", - (int) gid); - } - } - - if (gid_set && chown(dir, -1, gid) < 0) { - perror("chown[ctrl_interface]"); - goto fail; - } - - if (os_strlen(dir) + 1 + os_strlen(wpa_s->ifname) >= - sizeof(addr.sun_path)) - goto fail; - - priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0); - if (priv->sock < 0) { - perror("socket(PF_UNIX)"); - goto fail; - } - - os_memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - fname = wpa_supplicant_ctrl_iface_path(wpa_s); - if (fname == NULL) - goto fail; - os_strncpy(addr.sun_path, fname, sizeof(addr.sun_path)); - if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s", - strerror(errno)); - if (connect(priv->sock, (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(priv->sock, (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 (gid_set && chown(fname, -1, 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); - - eloop_register_read_sock(priv->sock, wpa_supplicant_ctrl_iface_receive, - wpa_s, priv); - wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb); - - os_free(buf); - return priv; - -fail: - if (priv->sock >= 0) - close(priv->sock); - os_free(priv); - if (fname) { - unlink(fname); - os_free(fname); - } - os_free(buf); - return NULL; -} - - -void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv) -{ - struct wpa_ctrl_dst *dst, *prev; - - if (priv->sock > -1) { - char *fname; - char *buf, *dir = NULL, *gid_str = NULL; - eloop_unregister_read_sock(priv->sock); - if (priv->ctrl_dst) { - /* - * Wait a second before closing the control socket if - * there are any attached monitors in order to allow - * them to receive any pending messages. - */ - wpa_printf(MSG_DEBUG, "CTRL_IFACE wait for attached " - "monitors to receive messages"); - os_sleep(1, 0); - } - close(priv->sock); - priv->sock = -1; - fname = wpa_supplicant_ctrl_iface_path(priv->wpa_s); - if (fname) { - unlink(fname); - os_free(fname); - } - - buf = os_strdup(priv->wpa_s->conf->ctrl_interface); - if (buf == NULL) - goto free_dst; - if (os_strncmp(buf, "DIR=", 4) == 0) { - dir = buf + 4; - gid_str = os_strstr(dir, " GROUP="); - if (gid_str) { - *gid_str = '\0'; - gid_str += 7; - } - } else - dir = buf; - - if (rmdir(dir) < 0) { - if (errno == ENOTEMPTY) { - wpa_printf(MSG_DEBUG, "Control interface " - "directory not empty - leaving it " - "behind"); - } else { - perror("rmdir[ctrl_interface]"); - } - } - os_free(buf); - } - -free_dst: - dst = priv->ctrl_dst; - while (dst) { - prev = dst; - dst = dst->next; - os_free(prev); - } - os_free(priv); -} - - -/** - * wpa_supplicant_ctrl_iface_send - Send a control interface packet to monitors - * @priv: Pointer to private data from wpa_supplicant_ctrl_iface_init() - * @level: Priority level of the message - * @buf: Message data - * @len: Message length - * - * Send a packet to all monitor programs attached to the control interface. - */ -static void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv, - int level, const char *buf, - size_t len) -{ - struct wpa_ctrl_dst *dst, *next; - char levelstr[10]; - int idx; - struct msghdr msg; - struct iovec io[2]; - - dst = priv->ctrl_dst; - if (priv->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 - - sizeof(dst->addr.sun_family)); - msg.msg_name = (void *) &dst->addr; - msg.msg_namelen = dst->addrlen; - if (sendmsg(priv->sock, &msg, 0) < 0) { - perror("sendmsg(CTRL_IFACE monitor)"); - dst->errors++; - if (dst->errors > 10) { - wpa_supplicant_ctrl_iface_detach( - priv, &dst->addr, - dst->addrlen); - } - } else - dst->errors = 0; - } - idx++; - dst = next; - } -} - - -void wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv) -{ - char buf[256]; - int res; - struct sockaddr_un from; - socklen_t fromlen = sizeof(from); - - for (;;) { - wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor to " - "attach", priv->wpa_s->ifname); - eloop_wait_for_read_sock(priv->sock); - - res = recvfrom(priv->sock, buf, sizeof(buf) - 1, 0, - (struct sockaddr *) &from, &fromlen); - if (res < 0) { - perror("recvfrom(ctrl_iface)"); - continue; - } - buf[res] = '\0'; - - if (os_strcmp(buf, "ATTACH") == 0) { - /* handle ATTACH signal of first monitor interface */ - if (!wpa_supplicant_ctrl_iface_attach(priv, &from, - fromlen)) { - sendto(priv->sock, "OK\n", 3, 0, - (struct sockaddr *) &from, fromlen); - /* OK to continue */ - return; - } else { - sendto(priv->sock, "FAIL\n", 5, 0, - (struct sockaddr *) &from, fromlen); - } - } else { - /* return FAIL for all other signals */ - sendto(priv->sock, "FAIL\n", 5, 0, - (struct sockaddr *) &from, fromlen); - } - } -} - - -/* Global ctrl_iface */ - -struct ctrl_iface_global_priv { - struct wpa_global *global; - int sock; -}; - - -static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, - void *sock_ctx) -{ - struct wpa_global *global = eloop_ctx; - char buf[256]; - int res; - struct sockaddr_un from; - socklen_t fromlen = sizeof(from); - char *reply; - size_t reply_len; - - res = recvfrom(sock, buf, sizeof(buf) - 1, 0, - (struct sockaddr *) &from, &fromlen); - if (res < 0) { - perror("recvfrom(ctrl_iface)"); - return; - } - buf[res] = '\0'; - - reply = wpa_supplicant_global_ctrl_iface_process(global, buf, - &reply_len); - - if (reply) { - sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, - fromlen); - os_free(reply); - } else if (reply_len) { - sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from, - fromlen); - } -} - - -struct ctrl_iface_global_priv * -wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global) -{ - struct ctrl_iface_global_priv *priv; - struct sockaddr_un addr; - - priv = os_zalloc(sizeof(*priv)); - if (priv == NULL) - return NULL; - priv->global = global; - priv->sock = -1; - - if (global->params.ctrl_interface == NULL) - return priv; - - wpa_printf(MSG_DEBUG, "Global control interface '%s'", - global->params.ctrl_interface); - - priv->sock = socket(PF_UNIX, SOCK_DGRAM, 0); - if (priv->sock < 0) { - perror("socket(PF_UNIX)"); - goto fail; - } - - os_memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - os_strncpy(addr.sun_path, global->params.ctrl_interface, - sizeof(addr.sun_path)); - if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror("bind(PF_UNIX)"); - if (connect(priv->sock, (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(global->params.ctrl_interface) < 0) { - perror("unlink[ctrl_iface]"); - wpa_printf(MSG_ERROR, "Could not unlink " - "existing ctrl_iface socket '%s'", - global->params.ctrl_interface); - goto fail; - } - if (bind(priv->sock, (struct sockaddr *) &addr, - sizeof(addr)) < 0) { - perror("bind(PF_UNIX)"); - goto fail; - } - wpa_printf(MSG_DEBUG, "Successfully replaced leftover " - "ctrl_iface socket '%s'", - global->params.ctrl_interface); - } 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", - global->params.ctrl_interface); - goto fail; - } - } - - eloop_register_read_sock(priv->sock, - wpa_supplicant_global_ctrl_iface_receive, - global, NULL); - - return priv; - -fail: - if (priv->sock >= 0) - close(priv->sock); - os_free(priv); - return NULL; -} - - -void -wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv) -{ - if (priv->sock >= 0) { - eloop_unregister_read_sock(priv->sock); - close(priv->sock); - } - if (priv->global->params.ctrl_interface) - unlink(priv->global->params.ctrl_interface); - os_free(priv); -} diff --git a/contrib/wpa_supplicant/dbus-wpa_supplicant.conf b/contrib/wpa_supplicant/dbus-wpa_supplicant.conf deleted file mode 100644 index 51a29e3a89c0..000000000000 --- a/contrib/wpa_supplicant/dbus-wpa_supplicant.conf +++ /dev/null @@ -1,16 +0,0 @@ -<!DOCTYPE busconfig PUBLIC - "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" - "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> -<busconfig> - <policy user="root"> - <allow own="fi.epitest.hostap.WPASupplicant"/> - - <allow send_destination="fi.epitest.hostap.WPASupplicant"/> - <allow send_interface="fi.epitest.hostap.WPASupplicant"/> - </policy> - <policy context="default"> - <deny own="fi.epitest.hostap.WPASupplicant"/> - <deny send_destination="fi.epitest.hostap.WPASupplicant"/> - <deny send_interface="fi.epitest.hostap.WPASupplicant"/> - </policy> -</busconfig> diff --git a/contrib/wpa_supplicant/dbus-wpa_supplicant.service b/contrib/wpa_supplicant/dbus-wpa_supplicant.service deleted file mode 100644 index a9ce1ecda63f..000000000000 --- a/contrib/wpa_supplicant/dbus-wpa_supplicant.service +++ /dev/null @@ -1,4 +0,0 @@ -[D-BUS Service] -Name=fi.epitest.hostap.WPASupplicant -Exec=/sbin/wpa_supplicant -u -User=root diff --git a/contrib/wpa_supplicant/dbus_dict_helpers.c b/contrib/wpa_supplicant/dbus_dict_helpers.c deleted file mode 100644 index b6ea55644335..000000000000 --- a/contrib/wpa_supplicant/dbus_dict_helpers.c +++ /dev/null @@ -1,979 +0,0 @@ -/* - * WPA Supplicant / dbus-based control interface - * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, 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 <dbus/dbus.h> -#include <string.h> -#include <stdio.h> -#include <stdlib.h> - -#include "common.h" -#include "dbus_dict_helpers.h" - - -/** - * Start a dict in a dbus message. Should be paired with a call to - * {@link wpa_dbus_dict_close_write}. - * - * @param iter A valid dbus message iterator - * @param iter_dict (out) A dict iterator to pass to further dict functions - * @return TRUE on success, FALSE on failure - * - */ -dbus_bool_t wpa_dbus_dict_open_write(DBusMessageIter *iter, - DBusMessageIter *iter_dict) -{ - dbus_bool_t result; - - if (!iter || !iter_dict) - return FALSE; - - result = dbus_message_iter_open_container( - iter, - DBUS_TYPE_ARRAY, - DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING - DBUS_TYPE_STRING_AS_STRING - DBUS_TYPE_VARIANT_AS_STRING - DBUS_DICT_ENTRY_END_CHAR_AS_STRING, - iter_dict); - return result; -} - - -/** - * End a dict element in a dbus message. Should be paired with - * a call to {@link wpa_dbus_dict_open_write}. - * - * @param iter valid dbus message iterator, same as passed to - * wpa_dbus_dict_open_write() - * @param iter_dict a dbus dict iterator returned from - * {@link wpa_dbus_dict_open_write} - * @return TRUE on success, FALSE on failure - * - */ -dbus_bool_t wpa_dbus_dict_close_write(DBusMessageIter *iter, - DBusMessageIter *iter_dict) -{ - if (!iter || !iter_dict) - return FALSE; - - return dbus_message_iter_close_container(iter, iter_dict); -} - - -static const char * _wpa_get_type_as_string_from_type(const int type) -{ - switch(type) { - case DBUS_TYPE_BYTE: - return DBUS_TYPE_BYTE_AS_STRING; - case DBUS_TYPE_BOOLEAN: - return DBUS_TYPE_BOOLEAN_AS_STRING; - case DBUS_TYPE_INT16: - return DBUS_TYPE_INT16_AS_STRING; - case DBUS_TYPE_UINT16: - return DBUS_TYPE_UINT16_AS_STRING; - case DBUS_TYPE_INT32: - return DBUS_TYPE_INT32_AS_STRING; - case DBUS_TYPE_UINT32: - return DBUS_TYPE_UINT32_AS_STRING; - case DBUS_TYPE_INT64: - return DBUS_TYPE_INT64_AS_STRING; - case DBUS_TYPE_UINT64: - return DBUS_TYPE_UINT64_AS_STRING; - case DBUS_TYPE_DOUBLE: - return DBUS_TYPE_DOUBLE_AS_STRING; - case DBUS_TYPE_STRING: - return DBUS_TYPE_STRING_AS_STRING; - case DBUS_TYPE_OBJECT_PATH: - return DBUS_TYPE_OBJECT_PATH_AS_STRING; - case DBUS_TYPE_ARRAY: - return DBUS_TYPE_ARRAY_AS_STRING; - default: - return NULL; - } -} - - -static dbus_bool_t _wpa_dbus_add_dict_entry_start( - DBusMessageIter *iter_dict, DBusMessageIter *iter_dict_entry, - const char *key, const int value_type) -{ - if (!dbus_message_iter_open_container(iter_dict, - DBUS_TYPE_DICT_ENTRY, NULL, - iter_dict_entry)) - return FALSE; - - if (!dbus_message_iter_append_basic(iter_dict_entry, DBUS_TYPE_STRING, - &key)) - return FALSE; - - return TRUE; -} - - -static dbus_bool_t _wpa_dbus_add_dict_entry_end( - DBusMessageIter *iter_dict, DBusMessageIter *iter_dict_entry, - DBusMessageIter *iter_dict_val) -{ - if (!dbus_message_iter_close_container(iter_dict_entry, iter_dict_val)) - return FALSE; - if (!dbus_message_iter_close_container(iter_dict, iter_dict_entry)) - return FALSE; - - return TRUE; -} - - -static dbus_bool_t _wpa_dbus_add_dict_entry_basic(DBusMessageIter *iter_dict, - const char *key, - const int value_type, - const void *value) -{ - DBusMessageIter iter_dict_entry, iter_dict_val; - const char *type_as_string = NULL; - - type_as_string = _wpa_get_type_as_string_from_type(value_type); - if (!type_as_string) - return FALSE; - - if (!_wpa_dbus_add_dict_entry_start(iter_dict, &iter_dict_entry, - key, value_type)) - return FALSE; - - if (!dbus_message_iter_open_container(&iter_dict_entry, - DBUS_TYPE_VARIANT, - type_as_string, &iter_dict_val)) - return FALSE; - - if (!dbus_message_iter_append_basic(&iter_dict_val, value_type, value)) - return FALSE; - - if (!_wpa_dbus_add_dict_entry_end(iter_dict, &iter_dict_entry, - &iter_dict_val)) - return FALSE; - - return TRUE; -} - - -static dbus_bool_t _wpa_dbus_add_dict_entry_byte_array( - DBusMessageIter *iter_dict, const char *key, - const char *value, const dbus_uint32_t value_len) -{ - DBusMessageIter iter_dict_entry, iter_dict_val, iter_array; - dbus_uint32_t i; - - if (!_wpa_dbus_add_dict_entry_start(iter_dict, &iter_dict_entry, - key, DBUS_TYPE_ARRAY)) - return FALSE; - - if (!dbus_message_iter_open_container(&iter_dict_entry, - DBUS_TYPE_VARIANT, - DBUS_TYPE_ARRAY_AS_STRING - DBUS_TYPE_BYTE_AS_STRING, - &iter_dict_val)) - return FALSE; - - if (!dbus_message_iter_open_container(&iter_dict_val, DBUS_TYPE_ARRAY, - DBUS_TYPE_BYTE_AS_STRING, - &iter_array)) - return FALSE; - - for (i = 0; i < value_len; i++) { - if (!dbus_message_iter_append_basic(&iter_array, - DBUS_TYPE_BYTE, - &(value[i]))) - return FALSE; - } - - if (!dbus_message_iter_close_container(&iter_dict_val, &iter_array)) - return FALSE; - - if (!_wpa_dbus_add_dict_entry_end(iter_dict, &iter_dict_entry, - &iter_dict_val)) - return FALSE; - - return TRUE; -} - - -/** - * Add a string entry to the dict. - * - * @param iter_dict A valid DBusMessageIter returned from - * {@link wpa_dbus_dict_open_write} - * @param key The key of the dict item - * @param value The string value - * @return TRUE on success, FALSE on failure - * - */ -dbus_bool_t wpa_dbus_dict_append_string(DBusMessageIter *iter_dict, - const char *key, const char *value) -{ - if (!key || !value) - return FALSE; - return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_STRING, - &value); -} - - -/** - * Add a byte entry to the dict. - * - * @param iter_dict A valid DBusMessageIter returned from - * {@link wpa_dbus_dict_open_write} - * @param key The key of the dict item - * @param value The byte value - * @return TRUE on success, FALSE on failure - * - */ -dbus_bool_t wpa_dbus_dict_append_byte(DBusMessageIter *iter_dict, - const char *key, const char value) -{ - if (!key) - return FALSE; - return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_BYTE, - &value); -} - - -/** - * Add a boolean entry to the dict. - * - * @param iter_dict A valid DBusMessageIter returned from - * {@link wpa_dbus_dict_open_write} - * @param key The key of the dict item - * @param value The boolean value - * @return TRUE on success, FALSE on failure - * - */ -dbus_bool_t wpa_dbus_dict_append_bool(DBusMessageIter *iter_dict, - const char *key, const dbus_bool_t value) -{ - if (!key) - return FALSE; - return _wpa_dbus_add_dict_entry_basic(iter_dict, key, - DBUS_TYPE_BOOLEAN, &value); -} - - -/** - * Add a 16-bit signed integer entry to the dict. - * - * @param iter_dict A valid DBusMessageIter returned from - * {@link wpa_dbus_dict_open_write} - * @param key The key of the dict item - * @param value The 16-bit signed integer value - * @return TRUE on success, FALSE on failure - * - */ -dbus_bool_t wpa_dbus_dict_append_int16(DBusMessageIter *iter_dict, - const char *key, - const dbus_int16_t value) -{ - if (!key) - return FALSE; - return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_INT16, - &value); -} - - -/** - * Add a 16-bit unsigned integer entry to the dict. - * - * @param iter_dict A valid DBusMessageIter returned from - * {@link wpa_dbus_dict_open_write} - * @param key The key of the dict item - * @param value The 16-bit unsigned integer value - * @return TRUE on success, FALSE on failure - * - */ -dbus_bool_t wpa_dbus_dict_append_uint16(DBusMessageIter *iter_dict, - const char *key, - const dbus_uint16_t value) -{ - if (!key) - return FALSE; - return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_UINT16, - &value); -} - - -/** - * Add a 32-bit signed integer to the dict. - * - * @param iter_dict A valid DBusMessageIter returned from - * {@link wpa_dbus_dict_open_write} - * @param key The key of the dict item - * @param value The 32-bit signed integer value - * @return TRUE on success, FALSE on failure - * - */ -dbus_bool_t wpa_dbus_dict_append_int32(DBusMessageIter *iter_dict, - const char *key, - const dbus_int32_t value) -{ - if (!key) - return FALSE; - return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_INT32, - &value); -} - - -/** - * Add a 32-bit unsigned integer entry to the dict. - * - * @param iter_dict A valid DBusMessageIter returned from - * {@link wpa_dbus_dict_open_write} - * @param key The key of the dict item - * @param value The 32-bit unsigned integer value - * @return TRUE on success, FALSE on failure - * - */ -dbus_bool_t wpa_dbus_dict_append_uint32(DBusMessageIter *iter_dict, - const char *key, - const dbus_uint32_t value) -{ - if (!key) - return FALSE; - return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_UINT32, - &value); -} - - -/** - * Add a 64-bit integer entry to the dict. - * - * @param iter_dict A valid DBusMessageIter returned from - * {@link wpa_dbus_dict_open_write} - * @param key The key of the dict item - * @param value The 64-bit integer value - * @return TRUE on success, FALSE on failure - * - */ -dbus_bool_t wpa_dbus_dict_append_int64(DBusMessageIter *iter_dict, - const char *key, - const dbus_int64_t value) -{ - if (!key) - return FALSE; - return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_INT64, - &value); -} - - -/** - * Add a 64-bit unsigned integer entry to the dict. - * - * @param iter_dict A valid DBusMessageIter returned from - * {@link wpa_dbus_dict_open_write} - * @param key The key of the dict item - * @param value The 64-bit unsigned integer value - * @return TRUE on success, FALSE on failure - * - */ -dbus_bool_t wpa_dbus_dict_append_uint64(DBusMessageIter *iter_dict, - const char *key, - const dbus_uint64_t value) -{ - if (!key) - return FALSE; - return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_UINT64, - &value); -} - - -/** - * Add a double-precision floating point entry to the dict. - * - * @param iter_dict A valid DBusMessageIter returned from - * {@link wpa_dbus_dict_open_write} - * @param key The key of the dict item - * @param value The double-precision floating point value - * @return TRUE on success, FALSE on failure - * - */ -dbus_bool_t wpa_dbus_dict_append_double(DBusMessageIter *iter_dict, - const char * key, - const double value) -{ - if (!key) - return FALSE; - return _wpa_dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_DOUBLE, - &value); -} - - -/** - * Add a DBus object path entry to the dict. - * - * @param iter_dict A valid DBusMessageIter returned from - * {@link wpa_dbus_dict_open_write} - * @param key The key of the dict item - * @param value The DBus object path value - * @return TRUE on success, FALSE on failure - * - */ -dbus_bool_t wpa_dbus_dict_append_object_path(DBusMessageIter *iter_dict, - const char *key, - const char *value) -{ - if (!key || !value) - return FALSE; - return _wpa_dbus_add_dict_entry_basic(iter_dict, key, - DBUS_TYPE_OBJECT_PATH, &value); -} - - -/** - * Add a byte array entry to the dict. - * - * @param iter_dict A valid DBusMessageIter returned from - * {@link wpa_dbus_dict_open_write} - * @param key The key of the dict item - * @param value The byte array - * @param value_len The length of the byte array, in bytes - * @return TRUE on success, FALSE on failure - * - */ -dbus_bool_t wpa_dbus_dict_append_byte_array(DBusMessageIter *iter_dict, - const char *key, - const char *value, - const dbus_uint32_t value_len) -{ - if (!key) - return FALSE; - if (!value && (value_len != 0)) - return FALSE; - return _wpa_dbus_add_dict_entry_byte_array(iter_dict, key, value, - value_len); -} - - -/** - * Begin a string array entry in the dict - * - * @param iter_dict A valid DBusMessageIter returned from - * {@link nmu_dbus_dict_open_write} - * @param key The key of the dict item - * @param iter_dict_entry A private DBusMessageIter provided by the caller to - * be passed to {@link wpa_dbus_dict_end_string_array} - * @param iter_dict_val A private DBusMessageIter provided by the caller to - * be passed to {@link wpa_dbus_dict_end_string_array} - * @param iter_array On return, the DBusMessageIter to be passed to - * {@link wpa_dbus_dict_string_array_add_element} - * @return TRUE on success, FALSE on failure - * - */ -dbus_bool_t wpa_dbus_dict_begin_string_array(DBusMessageIter *iter_dict, - const char *key, - DBusMessageIter *iter_dict_entry, - DBusMessageIter *iter_dict_val, - DBusMessageIter *iter_array) -{ - if (!iter_dict || !iter_dict_entry || !iter_dict_val || !iter_array) - return FALSE; - - if (!_wpa_dbus_add_dict_entry_start(iter_dict, iter_dict_entry, - key, DBUS_TYPE_ARRAY)) - return FALSE; - - if (!dbus_message_iter_open_container(iter_dict_entry, - DBUS_TYPE_VARIANT, - DBUS_TYPE_ARRAY_AS_STRING - DBUS_TYPE_STRING_AS_STRING, - iter_dict_val)) - return FALSE; - - if (!dbus_message_iter_open_container(iter_dict_val, DBUS_TYPE_ARRAY, - DBUS_TYPE_BYTE_AS_STRING, - iter_array)) - return FALSE; - - return TRUE; -} - - -/** - * Add a single string element to a string array dict entry - * - * @param iter_array A valid DBusMessageIter returned from - * {@link wpa_dbus_dict_begin_string_array}'s - * iter_array parameter - * @param elem The string element to be added to the dict entry's string array - * @return TRUE on success, FALSE on failure - * - */ -dbus_bool_t wpa_dbus_dict_string_array_add_element(DBusMessageIter *iter_array, - const char *elem) -{ - if (!iter_array || !elem) - return FALSE; - - return dbus_message_iter_append_basic(iter_array, DBUS_TYPE_STRING, - &elem); -} - - -/** - * End a string array dict entry - * - * @param iter_dict A valid DBusMessageIter returned from - * {@link nmu_dbus_dict_open_write} - * @param iter_dict_entry A private DBusMessageIter returned from - * {@link wpa_dbus_dict_end_string_array} - * @param iter_dict_val A private DBusMessageIter returned from - * {@link wpa_dbus_dict_end_string_array} - * @param iter_array A DBusMessageIter returned from - * {@link wpa_dbus_dict_end_string_array} - * @return TRUE on success, FALSE on failure - * - */ -dbus_bool_t wpa_dbus_dict_end_string_array(DBusMessageIter *iter_dict, - DBusMessageIter *iter_dict_entry, - DBusMessageIter *iter_dict_val, - DBusMessageIter *iter_array) -{ - if (!iter_dict || !iter_dict_entry || !iter_dict_val || !iter_array) - return FALSE; - - if (!dbus_message_iter_close_container(iter_dict_val, iter_array)) - return FALSE; - - if (!_wpa_dbus_add_dict_entry_end(iter_dict, iter_dict_entry, - iter_dict_val)) - return FALSE; - - return TRUE; -} - - -/** - * Convenience function to add an entire string array to the dict. - * - * @param iter_dict A valid DBusMessageIter returned from - * {@link nmu_dbus_dict_open_write} - * @param key The key of the dict item - * @param items The array of strings - * @param num_items The number of strings in the array - * @return TRUE on success, FALSE on failure - * - */ -dbus_bool_t wpa_dbus_dict_append_string_array(DBusMessageIter *iter_dict, - const char *key, - const char **items, - const dbus_uint32_t num_items) -{ - DBusMessageIter iter_dict_entry, iter_dict_val, iter_array; - dbus_uint32_t i; - - if (!key) - return FALSE; - if (!items && (num_items != 0)) - return FALSE; - - if (!wpa_dbus_dict_begin_string_array(iter_dict, key, - &iter_dict_entry, &iter_dict_val, - &iter_array)) - return FALSE; - - for (i = 0; i < num_items; i++) { - if (!wpa_dbus_dict_string_array_add_element(&iter_array, - items[i])) - return FALSE; - } - - if (!wpa_dbus_dict_end_string_array(iter_dict, &iter_dict_entry, - &iter_dict_val, &iter_array)) - return FALSE; - - return TRUE; -} - - -/*****************************************************/ -/* Stuff for reading dicts */ -/*****************************************************/ - -/** - * Start reading from a dbus dict. - * - * @param iter A valid DBusMessageIter pointing to the start of the dict - * @param iter_dict (out) A DBusMessageIter to be passed to - * {@link wpa_dbus_dict_read_next_entry} - * @return TRUE on success, FALSE on failure - * - */ -dbus_bool_t wpa_dbus_dict_open_read(DBusMessageIter *iter, - DBusMessageIter *iter_dict) -{ - if (!iter || !iter_dict) - return FALSE; - - if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY || - dbus_message_iter_get_element_type(iter) != DBUS_TYPE_DICT_ENTRY) - return FALSE; - - dbus_message_iter_recurse(iter, iter_dict); - return TRUE; -} - - -#define BYTE_ARRAY_CHUNK_SIZE 34 -#define BYTE_ARRAY_ITEM_SIZE (sizeof (char)) - -static dbus_bool_t _wpa_dbus_dict_entry_get_byte_array( - DBusMessageIter *iter, int array_type, - struct wpa_dbus_dict_entry *entry) -{ - dbus_uint32_t count = 0; - dbus_bool_t success = FALSE; - char *buffer; - - entry->bytearray_value = NULL; - entry->array_type = DBUS_TYPE_BYTE; - - buffer = wpa_zalloc(BYTE_ARRAY_ITEM_SIZE * BYTE_ARRAY_CHUNK_SIZE); - if (!buffer) { - perror("_wpa_dbus_dict_entry_get_byte_array[dbus]: out of " - "memory"); - goto done; - } - - entry->bytearray_value = buffer; - entry->array_len = 0; - while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_BYTE) { - char byte; - - if ((count % BYTE_ARRAY_CHUNK_SIZE) == 0 && count != 0) { - buffer = realloc(buffer, BYTE_ARRAY_ITEM_SIZE * - (count + BYTE_ARRAY_CHUNK_SIZE)); - if (buffer == NULL) { - perror("_wpa_dbus_dict_entry_get_byte_array[" - "dbus] out of memory trying to " - "retrieve the string array"); - goto done; - } - } - entry->bytearray_value = buffer; - - dbus_message_iter_get_basic(iter, &byte); - entry->bytearray_value[count] = byte; - entry->array_len = ++count; - dbus_message_iter_next(iter); - } - - /* Zero-length arrays are valid. */ - if (entry->array_len == 0) { - free(entry->bytearray_value); - entry->bytearray_value = NULL; - } - - success = TRUE; - -done: - return success; -} - - -#define STR_ARRAY_CHUNK_SIZE 8 -#define STR_ARRAY_ITEM_SIZE (sizeof (char *)) - -static dbus_bool_t _wpa_dbus_dict_entry_get_string_array( - DBusMessageIter *iter, int array_type, - struct wpa_dbus_dict_entry *entry) -{ - dbus_uint32_t count = 0; - dbus_bool_t success = FALSE; - char **buffer; - - entry->strarray_value = NULL; - entry->array_type = DBUS_TYPE_STRING; - - buffer = wpa_zalloc(STR_ARRAY_ITEM_SIZE * STR_ARRAY_CHUNK_SIZE); - if (buffer == NULL) { - perror("_wpa_dbus_dict_entry_get_string_array[dbus] out of " - "memory trying to retrieve a string array"); - goto done; - } - - entry->strarray_value = buffer; - entry->array_len = 0; - while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRING) { - const char *value; - char *str; - - if ((count % STR_ARRAY_CHUNK_SIZE) == 0 && count != 0) { - buffer = realloc(buffer, STR_ARRAY_ITEM_SIZE * - (count + STR_ARRAY_CHUNK_SIZE)); - if (buffer == NULL) { - perror("_wpa_dbus_dict_entry_get_string_array[" - "dbus] out of memory trying to " - "retrieve the string array"); - goto done; - } - } - entry->strarray_value = buffer; - - dbus_message_iter_get_basic(iter, &value); - str = strdup(value); - if (str == NULL) { - perror("_wpa_dbus_dict_entry_get_string_array[dbus] " - "out of memory trying to duplicate the string " - "array"); - goto done; - } - entry->strarray_value[count] = str; - entry->array_len = ++count; - dbus_message_iter_next(iter); - } - - /* Zero-length arrays are valid. */ - if (entry->array_len == 0) { - free(entry->strarray_value); - entry->strarray_value = NULL; - } - - success = TRUE; - -done: - return success; -} - - -static dbus_bool_t _wpa_dbus_dict_entry_get_array( - DBusMessageIter *iter_dict_val, struct wpa_dbus_dict_entry *entry) -{ - int array_type = dbus_message_iter_get_element_type(iter_dict_val); - dbus_bool_t success = FALSE; - DBusMessageIter iter_array; - - if (!entry) - return FALSE; - - dbus_message_iter_recurse(iter_dict_val, &iter_array); - - switch (array_type) { - case DBUS_TYPE_BYTE: - success = _wpa_dbus_dict_entry_get_byte_array(&iter_array, - array_type, - entry); - break; - case DBUS_TYPE_STRING: - success = _wpa_dbus_dict_entry_get_string_array(&iter_array, - array_type, - entry); - break; - default: - break; - } - - return success; -} - - -static dbus_bool_t _wpa_dbus_dict_fill_value_from_variant( - struct wpa_dbus_dict_entry *entry, DBusMessageIter *iter_dict_val) -{ - dbus_bool_t success = TRUE; - - switch (entry->type) { - case DBUS_TYPE_STRING: { - const char *v; - dbus_message_iter_get_basic(iter_dict_val, &v); - entry->str_value = strdup(v); - break; - } - case DBUS_TYPE_BOOLEAN: { - dbus_bool_t v; - dbus_message_iter_get_basic(iter_dict_val, &v); - entry->bool_value = v; - break; - } - case DBUS_TYPE_BYTE: { - char v; - dbus_message_iter_get_basic(iter_dict_val, &v); - entry->byte_value = v; - break; - } - case DBUS_TYPE_INT16: { - dbus_int16_t v; - dbus_message_iter_get_basic(iter_dict_val, &v); - entry->int16_value = v; - break; - } - case DBUS_TYPE_UINT16: { - dbus_uint16_t v; - dbus_message_iter_get_basic(iter_dict_val, &v); - entry->uint16_value = v; - break; - } - case DBUS_TYPE_INT32: { - dbus_int32_t v; - dbus_message_iter_get_basic(iter_dict_val, &v); - entry->int32_value = v; - break; - } - case DBUS_TYPE_UINT32: { - dbus_uint32_t v; - dbus_message_iter_get_basic(iter_dict_val, &v); - entry->uint32_value = v; - break; - } - case DBUS_TYPE_INT64: { - dbus_int64_t v; - dbus_message_iter_get_basic(iter_dict_val, &v); - entry->int64_value = v; - break; - } - case DBUS_TYPE_UINT64: { - dbus_uint64_t v; - dbus_message_iter_get_basic(iter_dict_val, &v); - entry->uint64_value = v; - break; - } - case DBUS_TYPE_DOUBLE: { - double v; - dbus_message_iter_get_basic(iter_dict_val, &v); - entry->double_value = v; - break; - } - case DBUS_TYPE_OBJECT_PATH: { - char *v; - dbus_message_iter_get_basic(iter_dict_val, &v); - entry->str_value = strdup(v); - break; - } - case DBUS_TYPE_ARRAY: { - success = _wpa_dbus_dict_entry_get_array(iter_dict_val, entry); - break; - } - default: - success = FALSE; - break; - } - - return success; -} - - -/** - * Read the current key/value entry from the dict. Entries are dynamically - * allocated when needed and must be freed after use with the - * {@link wpa_dbus_dict_entry_clear} function. - * - * The returned entry object will be filled with the type and value of the next - * entry in the dict, or the type will be DBUS_TYPE_INVALID if an error - * occurred. - * - * @param iter_dict A valid DBusMessageIter returned from - * {@link wpa_dbus_dict_open_read} - * @param entry A valid dict entry object into which the dict key and value - * will be placed - * @return TRUE on success, FALSE on failure - * - */ -dbus_bool_t wpa_dbus_dict_get_entry(DBusMessageIter *iter_dict, - struct wpa_dbus_dict_entry * entry) -{ - DBusMessageIter iter_dict_entry, iter_dict_val; - int type; - const char *key; - - if (!iter_dict || !entry) - goto error; - - if (dbus_message_iter_get_arg_type(iter_dict) != DBUS_TYPE_DICT_ENTRY) - goto error; - - dbus_message_iter_recurse(iter_dict, &iter_dict_entry); - dbus_message_iter_get_basic(&iter_dict_entry, &key); - entry->key = key; - - if (!dbus_message_iter_next(&iter_dict_entry)) - goto error; - type = dbus_message_iter_get_arg_type(&iter_dict_entry); - if (type != DBUS_TYPE_VARIANT) - goto error; - - dbus_message_iter_recurse(&iter_dict_entry, &iter_dict_val); - entry->type = dbus_message_iter_get_arg_type(&iter_dict_val); - if (!_wpa_dbus_dict_fill_value_from_variant(entry, &iter_dict_val)) - goto error; - - dbus_message_iter_next(iter_dict); - return TRUE; - -error: - if (entry) { - wpa_dbus_dict_entry_clear(entry); - entry->type = DBUS_TYPE_INVALID; - entry->array_type = DBUS_TYPE_INVALID; - } - - return FALSE; -} - - -/** - * Return whether or not there are additional dictionary entries. - * - * @param iter_dict A valid DBusMessageIter returned from - * {@link wpa_dbus_dict_open_read} - * @return TRUE if more dict entries exists, FALSE if no more dict entries - * exist - */ -dbus_bool_t wpa_dbus_dict_has_dict_entry(DBusMessageIter *iter_dict) -{ - if (!iter_dict) { - perror("wpa_dbus_dict_has_dict_entry[dbus]: out of memory"); - return FALSE; - } - return dbus_message_iter_get_arg_type(iter_dict) == - DBUS_TYPE_DICT_ENTRY; -} - - -/** - * Free any memory used by the entry object. - * - * @param entry The entry object - */ -void wpa_dbus_dict_entry_clear(struct wpa_dbus_dict_entry *entry) -{ - if (!entry) - return; - switch (entry->type) { - case DBUS_TYPE_OBJECT_PATH: - case DBUS_TYPE_STRING: - free(entry->str_value); - break; - case DBUS_TYPE_ARRAY: - switch (entry->array_type) { - case DBUS_TYPE_BYTE: { - free(entry->bytearray_value); - break; - } - case DBUS_TYPE_STRING: { - unsigned int i; - for (i = 0; i < entry->array_len; i++) - free(entry->strarray_value[i]); - free(entry->strarray_value); - break; - } - } - break; - } - - memset(entry, 0, sizeof(struct wpa_dbus_dict_entry)); -} diff --git a/contrib/wpa_supplicant/dbus_dict_helpers.h b/contrib/wpa_supplicant/dbus_dict_helpers.h deleted file mode 100644 index f873efcbcb13..000000000000 --- a/contrib/wpa_supplicant/dbus_dict_helpers.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * WPA Supplicant / dbus-based control interface - * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, 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 DBUS_DICT_HELPERS_H -#define DBUS_DICT_HELPERS_H - -/* - * Adding a dict to a DBusMessage - */ - -dbus_bool_t wpa_dbus_dict_open_write(DBusMessageIter *iter, - DBusMessageIter *iter_dict); - -dbus_bool_t wpa_dbus_dict_close_write(DBusMessageIter *iter, - DBusMessageIter *iter_dict); - -dbus_bool_t wpa_dbus_dict_append_string(DBusMessageIter *iter_dict, - const char *key, const char *value); - -dbus_bool_t wpa_dbus_dict_append_byte(DBusMessageIter *iter_dict, - const char *key, const char value); - -dbus_bool_t wpa_dbus_dict_append_bool(DBusMessageIter *iter_dict, - const char *key, - const dbus_bool_t value); - -dbus_bool_t wpa_dbus_dict_append_int16(DBusMessageIter *iter_dict, - const char *key, - const dbus_int16_t value); - -dbus_bool_t wpa_dbus_dict_append_uint16(DBusMessageIter *iter_dict, - const char *key, - const dbus_uint16_t value); - -dbus_bool_t wpa_dbus_dict_append_int32(DBusMessageIter *iter_dict, - const char *key, - const dbus_int32_t value); - -dbus_bool_t wpa_dbus_dict_append_uint32(DBusMessageIter *iter_dict, - const char *key, - const dbus_uint32_t value); - -dbus_bool_t wpa_dbus_dict_append_int64(DBusMessageIter *iter_dict, - const char *key, - const dbus_int64_t value); - -dbus_bool_t wpa_dbus_dict_append_uint64(DBusMessageIter *iter_dict, - const char *key, - const dbus_uint64_t value); - -dbus_bool_t wpa_dbus_dict_append_double(DBusMessageIter *iter_dict, - const char *key, - const double value); - -dbus_bool_t wpa_dbus_dict_append_object_path(DBusMessageIter *iter_dict, - const char *key, - const char *value); - -dbus_bool_t wpa_dbus_dict_append_byte_array(DBusMessageIter *iter_dict, - const char *key, - const char *value, - const dbus_uint32_t value_len); - -/* Manual construction and addition of string array elements */ -dbus_bool_t wpa_dbus_dict_begin_string_array(DBusMessageIter *iter_dict, - const char *key, - DBusMessageIter *iter_dict_entry, - DBusMessageIter *iter_dict_val, - DBusMessageIter *iter_array); - -dbus_bool_t wpa_dbus_dict_string_array_add_element(DBusMessageIter *iter_array, - const char *elem); - -dbus_bool_t wpa_dbus_dict_end_string_array(DBusMessageIter *iter_dict, - DBusMessageIter *iter_dict_entry, - DBusMessageIter *iter_dict_val, - DBusMessageIter *iter_array); - -/* Convenience function to add a whole string list */ -dbus_bool_t wpa_dbus_dict_append_string_array(DBusMessageIter *iter_dict, - const char *key, - const char **items, - const dbus_uint32_t num_items); - -/* - * Reading a dict from a DBusMessage - */ - -struct wpa_dbus_dict_entry { - int type; /** the dbus type of the dict entry's value */ - int array_type; /** the dbus type of the array elements if the dict - entry value contains an array */ - const char *key; /** key of the dict entry */ - - /** Possible values of the property */ - union { - char *str_value; - char byte_value; - dbus_bool_t bool_value; - dbus_int16_t int16_value; - dbus_uint16_t uint16_value; - dbus_int32_t int32_value; - dbus_uint32_t uint32_value; - dbus_int64_t int64_value; - dbus_uint64_t uint64_value; - double double_value; - char *bytearray_value; - char **strarray_value; - }; - dbus_uint32_t array_len; /** length of the array if the dict entry's - value contains an array */ -}; - -dbus_bool_t wpa_dbus_dict_open_read(DBusMessageIter *iter, - DBusMessageIter *iter_dict); - -dbus_bool_t wpa_dbus_dict_get_entry(DBusMessageIter *iter_dict, - struct wpa_dbus_dict_entry *entry); - -dbus_bool_t wpa_dbus_dict_has_dict_entry(DBusMessageIter *iter_dict); - -void wpa_dbus_dict_entry_clear(struct wpa_dbus_dict_entry *entry); - -#endif /* DBUS_DICT_HELPERS_H */ diff --git a/contrib/wpa_supplicant/defconfig b/contrib/wpa_supplicant/defconfig deleted file mode 100644 index 73e5da555915..000000000000 --- a/contrib/wpa_supplicant/defconfig +++ /dev/null @@ -1,326 +0,0 @@ -# Example wpa_supplicant 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 cases, these lines should use += in order not -# to override previous values of the variables. - - -# Uncomment following two lines and fix the paths if you have installed OpenSSL -# or GnuTLS in non-default location -#CFLAGS += -I/usr/local/openssl/include -#LIBS += -L/usr/local/openssl/lib - -# Some Red Hat versions seem to include kerberos header files from OpenSSL, but -# the kerberos files are not in the default include path. Following line can be -# used to fix build issues on such systems (krb5.h not found). -#CFLAGS += -I/usr/include/kerberos - -# Example configuration for various cross-compilation platforms - -#### sveasoft (e.g., for Linksys WRT54G) ###################################### -#CC=mipsel-uclibc-gcc -#CC=/opt/brcm/hndtools-mipsel-uclibc/bin/mipsel-uclibc-gcc -#CFLAGS += -Os -#CPPFLAGS += -I../src/include -I../../src/router/openssl/include -#LIBS += -L/opt/brcm/hndtools-mipsel-uclibc-0.9.19/lib -lssl -############################################################################### - -#### openwrt (e.g., for Linksys WRT54G) ####################################### -#CC=mipsel-uclibc-gcc -#CC=/opt/brcm/hndtools-mipsel-uclibc/bin/mipsel-uclibc-gcc -#CFLAGS += -Os -#CPPFLAGS=-I../src/include -I../openssl-0.9.7d/include \ -# -I../WRT54GS/release/src/include -#LIBS = -lssl -############################################################################### - - -# Driver interface for Host AP driver -CONFIG_DRIVER_HOSTAP=y - -# Driver interface for Agere driver -#CONFIG_DRIVER_HERMES=y -# Change include directories to match with the local setup -#CFLAGS += -I../../hcf -I../../include -I../../include/hcf -#CFLAGS += -I../../include/wireless - -# Driver interface for madwifi driver -#CONFIG_DRIVER_MADWIFI=y -# Change include directories to match with the local setup -#CFLAGS += -I../madwifi/wpa - -# Driver interface for Prism54 driver -# (Note: Prism54 is not yet supported, i.e., this will not work as-is and is -# for developers only) -#CONFIG_DRIVER_PRISM54=y - -# Driver interface for ndiswrapper -#CONFIG_DRIVER_NDISWRAPPER=y - -# Driver interface for Atmel driver -CONFIG_DRIVER_ATMEL=y - -# Driver interface for Broadcom driver -#CONFIG_DRIVER_BROADCOM=y -# Example path for wlioctl.h; change to match your configuration -#CFLAGS += -I/opt/WRT54GS/release/src/include - -# Driver interface for Intel ipw2100/2200 driver -#CONFIG_DRIVER_IPW=y - -# Driver interface for generic Linux wireless extensions -CONFIG_DRIVER_WEXT=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 - -# Driver interface for Windows NDIS -#CONFIG_DRIVER_NDIS=y -#CFLAGS += -I/usr/include/w32api/ddk -#LIBS += -L/usr/local/lib -# For native build using mingw -#CONFIG_NATIVE_WINDOWS=y -# Additional directories for cross-compilation on Linux host for mingw target -#CFLAGS += -I/opt/mingw/mingw32/include/ddk -#LIBS += -L/opt/mingw/mingw32/lib -#CC=mingw32-gcc -# By default, driver_ndis uses WinPcap for low-level operations. This can be -# replaced with the following option which replaces WinPcap calls with NDISUIO. -# However, this requires that WZC is disabled (net stop wzcsvc) before starting -# wpa_supplicant. -# CONFIG_USE_NDISUIO=y - -# Driver interface for development testing -#CONFIG_DRIVER_TEST=y - -# Driver interface for wired Ethernet drivers -CONFIG_DRIVER_WIRED=y - -# Enable IEEE 802.1X Supplicant (automatically included if any EAP method is -# included) -CONFIG_IEEE8021X_EAPOL=y - -# EAP-MD5 -CONFIG_EAP_MD5=y - -# EAP-MSCHAPv2 -CONFIG_EAP_MSCHAPV2=y - -# EAP-TLS -CONFIG_EAP_TLS=y - -# EAL-PEAP -CONFIG_EAP_PEAP=y - -# EAP-TTLS -CONFIG_EAP_TTLS=y - -# EAP-FAST -# 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.8d-tls-extensions.patch) -# to add the needed functions. -#CONFIG_EAP_FAST=y - -# EAP-GTC -CONFIG_EAP_GTC=y - -# EAP-OTP -CONFIG_EAP_OTP=y - -# EAP-SIM (enable CONFIG_PCSC, if EAP-SIM is used) -#CONFIG_EAP_SIM=y - -# EAP-PSK (experimental; this is _not_ needed for WPA-PSK) -#CONFIG_EAP_PSK=y - -# EAP-PAX -#CONFIG_EAP_PAX=y - -# LEAP -CONFIG_EAP_LEAP=y - -# EAP-AKA (enable CONFIG_PCSC, if EAP-AKA is used) -#CONFIG_EAP_AKA=y - -# EAP-SAKE -#CONFIG_EAP_SAKE=y - -# EAP-GPSK -#CONFIG_EAP_GPSK=y -# Include support for optional SHA256 cipher suite in EAP-GPSK -#CONFIG_EAP_GPSK_SHA256=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 - -# Smartcard support (i.e., private key on a smartcard), e.g., with openssl -# engine. -CONFIG_SMARTCARD=y - -# PC/SC interface for smartcards (USIM, GSM SIM) -# Enable this if EAP-SIM or EAP-AKA is included -#CONFIG_PCSC=y - -# Development testing -#CONFIG_EAPOL_TEST=y - -# Select control interface backend for external programs, e.g, wpa_cli: -# unix = UNIX domain sockets (default for Linux/*BSD) -# udp = UDP sockets using localhost (127.0.0.1) -# named_pipe = Windows Named Pipe (default for Windows) -# y = use default (backwards compatibility) -# If this option is commented out, control interface is not included in the -# build. -CONFIG_CTRL_IFACE=y - -# Include support for GNU Readline and History Libraries in wpa_cli. -# When building a wpa_cli binary for distribution, please note that these -# libraries are licensed under GPL and as such, BSD license may not apply for -# the resulting binary. -#CONFIG_READLINE=y - -# Remove debugging code that is printing out debug message to stdout. -# This can be used to reduce the size of the wpa_supplicant considerably -# if debugging code is not needed. The size reduction can be around 35% -# (e.g., 90 kB). -#CONFIG_NO_STDOUT_DEBUG=y - -# Remove WPA support, e.g., for wired-only IEEE 802.1X supplicant, to save -# 35-50 kB in code size. -#CONFIG_NO_WPA=y - -# Remove WPA2 support. This allows WPA to be used, but removes WPA2 code to -# save about 1 kB in code size when building only WPA-Personal (no EAP support) -# or 6 kB if building for WPA-Enterprise. -#CONFIG_NO_WPA2=y - -# Remove AES extra functions. This can be used to reduce code size by about -# 1.5 kB by removing extra AES modes that are not needed for commonly used -# client configurations (they are needed for some EAP types). -#CONFIG_NO_AES_EXTRAS=y - -# Select configuration backend: -# file = text file (e.g., wpa_supplicant.conf; note: the configuration file -# path is given on command line, not here; this option is just used to -# select the backend that allows configuration files to be used) -# winreg = Windows registry (see win_example.reg for an example) -CONFIG_BACKEND=file - -# Select program entry point implementation: -# main = UNIX/POSIX like main() function (default) -# main_winsvc = Windows service (read parameters from registry) -# main_none = Very basic example (development use only) -#CONFIG_MAIN=main - -# Select wrapper for operatins system and C library specific functions -# unix = UNIX/POSIX like systems (default) -# win32 = Windows systems -# none = Empty template -#CONFIG_OS=unix - -# Select event loop implementation -# eloop = select() loop (default) -# eloop_win = Windows events and WaitForMultipleObject() loop -# eloop_none = Empty template -#CONFIG_ELOOP=eloop - -# Select layer 2 packet implementation -# linux = Linux packet socket (default) -# pcap = libpcap/libdnet/WinPcap -# freebsd = FreeBSD libpcap -# winpcap = WinPcap with receive thread -# ndis = Windows NDISUIO (note: requires CONFIG_USE_NDISUIO=y) -# none = Empty template -#CONFIG_L2_PACKET=linux - -# 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 - -# Select TLS implementation -# openssl = OpenSSL (default) -# gnutls = GnuTLS (needed for TLS/IA, see also CONFIG_GNUTLS_EXTRA) -# internal = Internal TLSv1 implementation (experimental) -# none = Empty template -#CONFIG_TLS=openssl - -# Whether to enable TLS/IA support, which is required for EAP-TTLSv1. -# You need CONFIG_TLS=gnutls for this to have any effect. Please note that -# even though the core GnuTLS library is released under LGPL, this extra -# library uses GPL and as such, the terms of GPL apply to the combination -# of wpa_supplicant and GnuTLS if this option is enabled. BSD license may not -# apply for distribution of the resulting binary. -#CONFIG_GNUTLS_EXTRA=y - -# If CONFIG_TLS=internal is used, additional library and include paths are -# needed for LibTomMath. Alternatively, an integrated, minimal version of -# LibTomMath can be used. See beginning of libtommath.c for details on benefits -# and drawbacks of this option. -#CONFIG_INTERNAL_LIBTOMMATH=y -#ifndef CONFIG_INTERNAL_LIBTOMMATH -#LTM_PATH=/usr/src/libtommath-0.39 -#CFLAGS += -I$(LTM_PATH) -#LIBS += -L$(LTM_PATH) -#LIBS_p += -L$(LTM_PATH) -#endif - -# Include NDIS event processing through WMI into wpa_supplicant/wpasvc. -# This is only for Windows builds and requires WMI-related header files and -# WbemUuid.Lib from Platform SDK even when building with MinGW. -#CONFIG_NDIS_EVENTS_INTEGRATED=y -#PLATFORMSDKLIB="/opt/Program Files/Microsoft Platform SDK/Lib" - -# Add support for DBus control interface -#CONFIG_CTRL_IFACE_DBUS=y - -# Add support for loading EAP methods dynamically as shared libraries. -# When this option is enabled, each EAP method can be either included -# statically (CONFIG_EAP_<method>=y) or dynamically (CONFIG_EAP_<method>=dyn). -# Dynamic EAP methods are build as shared objects (eap_*.so) and they need to -# be loaded in the beginning of the wpa_supplicant configuration file -# (see load_dynamic_eap parameter in the example file) before being used in -# the network blocks. -# -# Note that some shared parts of EAP methods are included in the main program -# and in order to be able to use dynamic EAP methods using these parts, the -# main program must have been build with the EAP method enabled (=y or =dyn). -# This means that EAP-TLS/PEAP/TTLS/FAST cannot be added as dynamic libraries -# unless at least one of them was included in the main build to force inclusion -# of the shared code. Similarly, at least one of EAP-SIM/AKA must be included -# in the main build to be able to load these methods dynamically. -# -# Please also note that using dynamic libraries will increase the total binary -# size. Thus, it may not be the best option for targets that have limited -# amount of memory/flash. -#CONFIG_DYNAMIC_EAP_METHODS=y - -# Include client MLME (management frame processing). -# This can be used to move MLME processing of Devicescape IEEE 802.11 stack -# into user space. -#CONFIG_CLIENT_MLME=y -# Currently, driver_devicescape.c build requires some additional parameters -# to be able to include some of the kernel header files. Following lines can -# be used to set these (WIRELESS_DEV must point to the root directory of the -# wireless-dev.git tree). -#WIRELESS_DEV=/usr/src/wireless-dev -#CFLAGS += -I$(WIRELESS_DEV)/net/mac80211 - -# Add support for writing debug log to a file (/tmp/wpa_supplicant-log-#.txt) -#CONFIG_DEBUG_FILE=y - -# Add support for logging via syslog -#CONFIG_DEBUG_SYSLOG=y diff --git a/contrib/wpa_supplicant/defs.h b/contrib/wpa_supplicant/defs.h deleted file mode 100644 index 603fc55c110a..000000000000 --- a/contrib/wpa_supplicant/defs.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * WPA Supplicant - Common definitions - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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; - - -typedef enum { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP, - WPA_ALG_IGTK, WPA_ALG_DHV } wpa_alg; -typedef enum { CIPHER_NONE, CIPHER_WEP40, CIPHER_TKIP, CIPHER_CCMP, - CIPHER_WEP104 } wpa_cipher; -typedef enum { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE, - KEY_MGMT_802_1X_NO_WPA, KEY_MGMT_WPA_NONE } wpa_key_mgmt; - -/** - * 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. - */ -typedef enum { - /** - * 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_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_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 -} wpa_states; - -#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 - -#endif /* DEFS_H */ diff --git a/contrib/wpa_supplicant/des.c b/contrib/wpa_supplicant/des.c deleted file mode 100644 index 8e0d56fc6af1..000000000000 --- a/contrib/wpa_supplicant/des.c +++ /dev/null @@ -1,476 +0,0 @@ -/* - * DES and 3DES-EDE ciphers - * - * Modifications to LibTomCrypt implementation: - * Copyright (c) 2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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" - - -#ifdef INTERNAL_DES - -/* - * 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]); -} - - -struct des3_key_s { - u32 ek[3][32]; - u32 dk[3][32]; -}; - -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]); -} - -#endif /* INTERNAL_DES */ diff --git a/contrib/wpa_supplicant/doc/code_structure.doxygen b/contrib/wpa_supplicant/doc/code_structure.doxygen deleted file mode 100644 index 23b7f22a05bc..000000000000 --- a/contrib/wpa_supplicant/doc/code_structure.doxygen +++ /dev/null @@ -1,270 +0,0 @@ -/** -\page code_structure Structure of the source code - -[ \ref wpa_supplicant_core "wpa_supplicant core functionality" | -\ref generic_helper_func "Generic helper functions" | -\ref crypto_func "Cryptographic functions" | -\ref configuration "Configuration" | -\ref ctrl_iface "Control interface" | -\ref wpa_code "WPA supplicant" | -\ref eap_peer "EAP peer" | -\ref eapol_supp "EAPOL supplicant" | -\ref win_port "Windows port" | -\ref test_programs "Test programs" ] - -%wpa_supplicant implementation is divided into number of independent -modules. Core code includes functionality for controlling the network -selection, association, and configuration. Independent modules include -WPA code (key handshake, PMKSA caching, pre-authentication), EAPOL -state machine, and EAP state machine and methods. In addition, there -are number of separate files for generic helper functions. - -Both WPA and EAPOL/EAP state machines can be used separately in other -programs than %wpa_supplicant. As an example, the included test -programs eapol_test and preauth_test are using these modules. - -\ref driver_wrapper "Driver interface API" is defined in driver.h and -all hardware/driver dependent functionality is implemented in -driver_*.c. - - -\section wpa_supplicant_core wpa_supplicant core functionality - -wpa_supplicant.c - Program initialization, main control loop - -main.c - main() for UNIX-like operating systems and MinGW (Windows); this - uses command line arguments to configure wpa_supplicant - -events.c - Driver event processing; wpa_supplicant_event() and related functions - -wpa_supplicant_i.h - Internal definitions for %wpa_supplicant core; should not be - included into independent modules - -wpa_supplicant.h - Definitions for driver event data and message logging - - -\section generic_helper_func Generic helper functions - -%wpa_supplicant uses generic helper functions some of which are shared -with with hostapd. The following C files are currently used: - -eloop.c and eloop.h - Event loop (select() loop with registerable timeouts, socket read - callbacks, and signal callbacks) - -common.c and common.h - Common helper functions - -defs.h - Definitions shared by multiple files - -l2_packet.h, l2_packet_linux.c, and l2_packet_pcap.c - Layer 2 (link) access wrapper (includes native Linux implementation - and wrappers for libdnet/libpcap). A new l2_packet implementation - may need to be added when porting to new operating systems that are - not supported by libdnet/libpcap. Makefile can be used to select which - l2_packet implementation is included. l2_packet_linux.c uses Linux - packet sockets and l2_packet_pcap.c has a more portable version using - libpcap and libdnet. - -pcsc_funcs.c and pcsc_funcs.h - Wrapper for PC/SC lite SIM and smart card readers - -priv_netlink.h - Private version of netlink definitions from Linux kernel header files; - this could be replaced with C library header file once suitable - version becomes commonly available - -version.h - Version number definitions - -wireless_copy.h - Private version of Linux wireless extensions definitions from kernel - header files; this could be replaced with C library header file once - suitable version becomes commonly available - - -\section crypto_func Cryptographic functions - -md5.c and md5.h - MD5 (replaced with a crypto library if TLS support is included) - HMAC-MD5 (keyed checksum for message authenticity validation) - -rc4.c and rc4.h - RC4 (broadcast/default key encryption) - -sha1.c and sha1.h - SHA-1 (replaced with a crypto library if TLS support is included) - HMAC-SHA-1 (keyed checksum for message authenticity validation) - PRF-SHA-1 (pseudorandom (key/nonce generation) function) - PBKDF2-SHA-1 (ASCII passphrase to shared secret) - T-PRF (for EAP-FAST) - TLS-PRF (RFC 2246) - -aes_wrap.c, aes_wrap.h, aes.c - AES (replaced with a crypto library if TLS support is included), - AES Key Wrap Algorithm with 128-bit KEK, RFC3394 (broadcast/default - key encryption), - One-Key CBC MAC (OMAC1) hash with AES-128, - AES-128 CTR mode encryption, - AES-128 EAX mode encryption/decryption, - AES-128 CBC - -crypto.h - Definition of crypto library wrapper - -crypto.c - Wrapper functions for libcrypto (OpenSSL) - -crypto_gnutls.c - Wrapper functions for libgcrypt (used by GnuTLS) - -ms_funcs.c and ms_funcs.h - Helper functions for MSCHAPV2 and LEAP - -tls.h - Definition of TLS library wrapper - -tls_none.c - Dummy implementation of TLS library wrapper for cases where TLS - functionality is not included. - -tls_openssl.c - TLS library wrapper for openssl - -tls_gnutls.c - TLS library wrapper for GnuTLS - - -\section configuration Configuration - -config_ssid.h - Definition of per network configuration items - -config.h - Definition of the %wpa_supplicant configuration - -config.c - Configuration parser and common functions - -config_file.c - Configuration backend for text files (e.g., wpa_supplicant.conf) - - -\section ctrl_iface Control interface - -%wpa_supplicant has a \ref ctrl_iface_page "control interface" -that can be used to get status -information and manage operations from external programs. An example -command line interface (wpa_cli) and GUI (wpa_gui) for this interface -are included in the %wpa_supplicant distribution. - -ctrl_iface.c and ctrl_iface.h - %wpa_supplicant-side of the control interface - -wpa_ctrl.c and wpa_ctrl.h - Library functions for external programs to provide access to the - %wpa_supplicant control interface - -wpa_cli.c - Example program for using %wpa_supplicant control interface - - -\section wpa_code WPA supplicant - -wpa.c and wpa.h - WPA state machine and 4-Way/Group Key Handshake processing - -preauth.c and preauth.h - PMKSA caching and pre-authentication (RSN/WPA2) - -wpa_i.h - Internal definitions for WPA code; not to be included to other modules. - -\section eap_peer EAP peer - -\ref eap_module "EAP peer implementation" is a separate module that -can be used by other programs than just %wpa_supplicant. - -eap.c and eap.h - EAP state machine and method interface - -eap_defs.h - Common EAP definitions - -eap_i.h - Internal definitions for EAP state machine and EAP methods; not to be - included in other modules - -eap_sim_common.c and eap_sim_common.h - Common code for EAP-SIM and EAP-AKA - -eap_tls_common.c and eap_tls_common.h - Common code for EAP-PEAP, EAP-TTLS, and EAP-FAST - -eap_tlv.c and eap_tlv.h - EAP-TLV code for EAP-PEAP and EAP-FAST - -eap_ttls.c and eap_ttls.h - EAP-TTLS - -eap_pax.c, eap_pax_common.h, eap_pax_common.c - EAP-PAX - -eap_psk.c, eap_psk_common.h, eap_psk_common.c - EAP-PSK (note: this is not needed for WPA-PSK) - -eap_sake.c, eap_sake_common.h, eap_sake_common.c - EAP-SAKE - -eap_gpsk.c, eap_gpsk_common.h, eap_gpsk_common.c - EAP-GPSK - -eap_aka.c, eap_fast.c, eap_gtc.c, eap_leap.c, eap_md5.c, eap_mschapv2.c, -eap_otp.c, eap_peap.c, eap_sim.c, eap_tls.c - Other EAP method implementations - - -\section eapol_supp EAPOL supplicant - -eapol_sm.c and eapol_sm.h - EAPOL supplicant state machine and IEEE 802.1X processing - - -\section win_port Windows port - -ndis_events.cpp - External program for receiving NdisMIndicateStatus() events and - delivering them to %wpa_supplicant in more easier to use form - -win_if_list.c - External program for listing current network interface - - -\section test_programs Test programs - -radius_client.c and radius_client.h - RADIUS authentication client implementation for eapol_test - -radius.c and radius.h - RADIUS message processing for eapol_test - -config_types.h and hostapd.h - Minimal version of hostapd header files for eapol_test - -eapol_test.c - Standalone EAP testing tool with integrated RADIUS authentication - client - -preauth_test.c - Standalone RSN pre-authentication tool - -wpa_passphrase.c - WPA ASCII passphrase to PSK conversion - -*/ diff --git a/contrib/wpa_supplicant/doc/ctrl_iface.doxygen b/contrib/wpa_supplicant/doc/ctrl_iface.doxygen deleted file mode 100644 index d64978664e14..000000000000 --- a/contrib/wpa_supplicant/doc/ctrl_iface.doxygen +++ /dev/null @@ -1,444 +0,0 @@ -/** -\page ctrl_iface_page Control interface - -%wpa_supplicant implements a control interface that can be used by -external programs to control the operations of the %wpa_supplicant -daemon and to get status information and event notifications. There is -a small C library, in a form of a single C file, wpa_ctrl.c, that -provides helper functions to facilitate the use of the control -interface. External programs can link this file into them and then use -the library functions documented in wpa_ctrl.h to interact with -%wpa_supplicant. This library can also be used with C++. wpa_cli.c and -wpa_gui are example programs using this library. - -There are multiple mechanisms for inter-process communication. For -example, Linux version of %wpa_supplicant is using UNIX domain sockets -for the control interface and Windows version UDP sockets. The use of -the functions defined in wpa_ctrl.h can be used to hide the details of -the used IPC from external programs. - - -\section using_ctrl_iface Using the control interface - -External programs, e.g., a GUI or a configuration utility, that need to -communicate with %wpa_supplicant should link in wpa_ctrl.c. This -allows them to use helper functions to open connection to the control -interface with wpa_ctrl_open() and to send commands with -wpa_ctrl_request(). - -%wpa_supplicant uses the control interface for two types of communication: -commands and unsolicited event messages. Commands are a pair of -messages, a request from the external program and a response from -%wpa_supplicant. These can be executed using wpa_ctrl_request(). -Unsolicited event messages are sent by %wpa_supplicant to the control -interface connection without specific request from the external program -for receiving each message. However, the external program needs to -attach to the control interface with wpa_ctrl_attach() to receive these -unsolicited messages. - -If the control interface connection is used both for commands and -unsolicited event messages, there is potential for receiving an -unsolicited message between the command request and response. -wpa_ctrl_request() caller will need to supply a callback, msg_cb, -for processing these messages. Often it is easier to open two -control interface connections by calling wpa_ctrl_open() twice and -then use one of the connections for commands and the other one for -unsolicited messages. This way command request/response pairs will -not be broken by unsolicited messages. wpa_cli is an example of how -to use only one connection for both purposes and wpa_gui demonstrates -how to use two separate connections. - -Once the control interface connection is not needed anymore, it should -be closed by calling wpa_ctrl_close(). If the connection was used for -unsolicited event messages, it should be first detached by calling -wpa_ctrl_detach(). - - -\section ctrl_iface_cmds Control interface commands - -Following commands can be used with wpa_ctrl_request(): - -\subsection ctrl_iface_PING PING - -This command can be used to test whether %wpa_supplicant is replying -to the control interface commands. The expected reply is \c PONG if the -connection is open and %wpa_supplicant is processing commands. - - -\subsection ctrl_iface_MIB MIB - -Request a list of MIB variables (dot1x, dot11). The output is a text -block with each line in \c variable=value format. For example: - -\verbatim -dot11RSNAOptionImplemented=TRUE -dot11RSNAPreauthenticationImplemented=TRUE -dot11RSNAEnabled=FALSE -dot11RSNAPreauthenticationEnabled=FALSE -dot11RSNAConfigVersion=1 -dot11RSNAConfigPairwiseKeysSupported=5 -dot11RSNAConfigGroupCipherSize=128 -dot11RSNAConfigPMKLifetime=43200 -dot11RSNAConfigPMKReauthThreshold=70 -dot11RSNAConfigNumberOfPTKSAReplayCounters=1 -dot11RSNAConfigSATimeout=60 -dot11RSNAAuthenticationSuiteSelected=00-50-f2-2 -dot11RSNAPairwiseCipherSelected=00-50-f2-4 -dot11RSNAGroupCipherSelected=00-50-f2-4 -dot11RSNAPMKIDUsed= -dot11RSNAAuthenticationSuiteRequested=00-50-f2-2 -dot11RSNAPairwiseCipherRequested=00-50-f2-4 -dot11RSNAGroupCipherRequested=00-50-f2-4 -dot11RSNAConfigNumberOfGTKSAReplayCounters=0 -dot11RSNA4WayHandshakeFailures=0 -dot1xSuppPaeState=5 -dot1xSuppHeldPeriod=60 -dot1xSuppAuthPeriod=30 -dot1xSuppStartPeriod=30 -dot1xSuppMaxStart=3 -dot1xSuppSuppControlledPortStatus=Authorized -dot1xSuppBackendPaeState=2 -dot1xSuppEapolFramesRx=0 -dot1xSuppEapolFramesTx=440 -dot1xSuppEapolStartFramesTx=2 -dot1xSuppEapolLogoffFramesTx=0 -dot1xSuppEapolRespFramesTx=0 -dot1xSuppEapolReqIdFramesRx=0 -dot1xSuppEapolReqFramesRx=0 -dot1xSuppInvalidEapolFramesRx=0 -dot1xSuppEapLengthErrorFramesRx=0 -dot1xSuppLastEapolFrameVersion=0 -dot1xSuppLastEapolFrameSource=00:00:00:00:00:00 -\endverbatim - - -\subsection ctrl_iface_STATUS STATUS - -Request current WPA/EAPOL/EAP status information. The output is a text -block with each line in \c variable=value format. For example: - -\verbatim -bssid=02:00:01:02:03:04 -ssid=test network -pairwise_cipher=CCMP -group_cipher=CCMP -key_mgmt=WPA-PSK -wpa_state=COMPLETED -ip_address=192.168.1.21 -Supplicant PAE state=AUTHENTICATED -suppPortStatus=Authorized -EAP state=SUCCESS -\endverbatim - - -\subsection ctrl_iface_STATUS-VERBOSE STATUS-VERBOSE - -Same as STATUS, but with more verbosity (i.e., more \c variable=value pairs). - -\verbatim -bssid=02:00:01:02:03:04 -ssid=test network -id=0 -pairwise_cipher=CCMP -group_cipher=CCMP -key_mgmt=WPA-PSK -wpa_state=COMPLETED -ip_address=192.168.1.21 -Supplicant PAE state=AUTHENTICATED -suppPortStatus=Authorized -heldPeriod=60 -authPeriod=30 -startPeriod=30 -maxStart=3 -portControl=Auto -Supplicant Backend state=IDLE -EAP state=SUCCESS -reqMethod=0 -methodState=NONE -decision=COND_SUCC -ClientTimeout=60 -\endverbatim - - -\subsection ctrl_iface_PMKSA PMKSA - -Show PMKSA cache - -\verbatim -Index / AA / PMKID / expiration (in seconds) / opportunistic -1 / 02:00:01:02:03:04 / 000102030405060708090a0b0c0d0e0f / 41362 / 0 -2 / 02:00:01:33:55:77 / 928389281928383b34afb34ba4212345 / 362 / 1 -\endverbatim - - -\subsection ctrl_iface_SET SET <variable> <value> - -Set variables: -- EAPOL::heldPeriod -- EAPOL::authPeriod -- EAPOL::startPeriod -- EAPOL::maxStart -- dot11RSNAConfigPMKLifetime -- dot11RSNAConfigPMKReauthThreshold -- dot11RSNAConfigSATimeout - -Example command: -\verbatim -SET EAPOL::heldPeriod 45 -\endverbatim - - -\subsection ctrl_iface_LOGON LOGON - -IEEE 802.1X EAPOL state machine logon. - - -\subsection ctrl_iface_LOGOFF LOGOFF - -IEEE 802.1X EAPOL state machine logoff. - - -\subsection ctrl_iface_REASSOCIATE REASSOCIATE - -Force reassociation. - - -\subsection ctrl_iface_RECONNECT RECONNECT - -Connect if disconnected (i.e., like \c REASSOCIATE, but only connect -if in disconnected state). - - -\subsection ctrl_iface_PREAUTH PREAUTH <BSSID> - -Start pre-authentication with the given BSSID. - - -\subsection ctrl_iface_ATTACH ATTACH - -Attach the connection as a monitor for unsolicited events. This can -be done with wpa_ctrl_attach(). - - -\subsection ctrl_iface_DETACH DETACH - -Detach the connection as a monitor for unsolicited events. This can -be done with wpa_ctrl_detach(). - - -\subsection ctrl_iface_LEVEL LEVEL <debug level> - -Change debug level. - - -\subsection ctrl_iface_RECONFIGURE RECONFIGURE - -Force %wpa_supplicant to re-read its configuration data. - - -\subsection ctrl_iface_TERMINATE TERMINATE - -Terminate %wpa_supplicant process. - - -\subsection ctrl_iface_BSSID BSSID <network id> <BSSID> - -Set preferred BSSID for a network. Network id can be received from the -\c LIST_NETWORKS command output. - - -\subsection ctrl_iface_LIST_NETWORKS LIST_NETWORKS - -List configured networks. - -\verbatim -network id / ssid / bssid / flags -0 example network any [CURRENT] -\endverbatim - -(note: fields are separated with tabs) - - -\subsection ctrl_iface_DISCONNECT DISCONNECT - -Disconnect and wait for \c REASSOCIATE or \c RECONNECT command before -connecting. - - -\subsection ctrl_iface_SCAN SCAN - -Request a new BSS scan. - - -\subsection ctrl_iface_SCAN_RESULTS SCAN_RESULTS - -Get the latest scan results. - -\verbatim -bssid / frequency / signal level / flags / ssid -00:09:5b:95:e0:4e 2412 208 [WPA-PSK-CCMP] jkm private -02:55:24:33:77:a3 2462 187 [WPA-PSK-TKIP] testing -00:09:5b:95:e0:4f 2412 209 jkm guest -\endverbatim - -(note: fields are separated with tabs) - - -\subsection ctrl_iface_SELECT_NETWORK SELECT_NETWORK <network id> - -Select a network (disable others). Network id can be received from the -\c LIST_NETWORKS command output. - - -\subsection ctrl_iface_ENABLE_NETWORK ENABLE_NETWORK <network id> - -Enable a network. Network id can be received from the -\c LIST_NETWORKS command output. - - -\subsection ctrl_iface_DISABLE_NETWORK DISABLE_NETWORK <network id> - -Disable a network. Network id can be received from the -\c LIST_NETWORKS command output. - - -\subsection ctrl_iface_ADD_NETWORK ADD_NETWORK - -Add a new network. This command creates a new network with empty -configuration. The new network is disabled and once it has been -configured it can be enabled with \c ENABLE_NETWORK command. \c ADD_NETWORK -returns the network id of the new network or FAIL on failure. - - -\subsection ctrl_iface_REMOVE_NETWORK REMOVE_NETWORK <network id> - -Remove a network. Network id can be received from the -\c LIST_NETWORKS command output. - - -\subsection ctrl_iface_SET_NETWORK SET_NETWORK <network id> <variable> <value> - -Set network variables. Network id can be received from the -\c LIST_NETWORKS command output. - -This command uses the same variables and data formats as the -configuration file. See example wpa_supplicant.conf for more details. - -- ssid (network name, SSID) -- psk (WPA passphrase or pre-shared key) -- key_mgmt (key management protocol) -- identity (EAP identity) -- password (EAP password) -- ... - - -\subsection ctrl_iface_GET_NETWORK GET_NETWORK <network id> <variable> - -Get network variables. Network id can be received from the -\c LIST_NETWORKS command output. - - -\subsection ctrl_iface_SAVE_CONFIG SAVE_CONFIG - -Save the current configuration. - - -\section ctrl_iface_interactive Interactive requests - -If %wpa_supplicant needs additional information during authentication -(e.g., password), it will use a specific prefix, \c CTRL-REQ- -(\a WPA_CTRL_REQ macro) in an unsolicited event message. An external -program, e.g., a GUI, can provide such information by using -\c CTRL-RSP- (\a WPA_CTRL_RSP macro) prefix in a command with matching -field name. - -The following fields can be requested in this way from the user: -- IDENTITY (EAP identity/user name) -- PASSWORD (EAP password) -- NEW_PASSWORD (New password if the server is requesting password change) -- PIN (PIN code for accessing a SIM or smartcard) -- OTP (one-time password; like password, but the value is used only once) -- PASSPHRASE (passphrase for a private key file) - -\verbatim -CTRL-REQ-<field name>-<network id>-<human readable text> -CTRL-RSP-<field name>-<network id>-<value> -\endverbatim - -For example, request from %wpa_supplicant: -\verbatim -CTRL-REQ-PASSWORD-1-Password needed for SSID test-network -\endverbatim - -And a matching reply from the GUI: -\verbatim -CTRL-RSP-PASSWORD-1-secret -\endverbatim - - -\subsection ctrl_iface_GET_CAPABILITY GET_CAPABILITY <option> [strict] - -Get list of supported functionality (eap, pairwise, group, -proto). Supported functionality is shown as space separate lists of -values used in the same format as in %wpa_supplicant configuration. -If optional argument, 'strict', is added, only the values that the -driver claims to explicitly support are included. Without this, all -available capabilities are included if the driver does not provide -a mechanism for querying capabilities. - -Example request/reply pairs: - -\verbatim -GET_CAPABILITY eap -AKA FAST GTC LEAP MD5 MSCHAPV2 OTP PAX PEAP PSK SIM TLS TTLS -\endverbatim - -\verbatim -GET_CAPABILITY pairwise -CCMP TKIP NONE -\endverbatim - -\verbatim -GET_CAPABILITY pairwise strict -\endverbatim - -\verbatim -GET_CAPABILITY group -CCMP TKIP WEP104 WEP40 -\endverbatim - -\verbatim -GET_CAPABILITY key_mgmt -WPA-PSK WPA-EAP IEEE8021X NONE -\endverbatim - -\verbatim -GET_CAPABILITY proto -RSN WPA -\endverbatim - -\verbatim -GET_CAPABILITY auth_alg -OPEN SHARED LEAP -\endverbatim - - -\subsection ctrl_iface_AP_SCAN AP_SCAN <ap_scan value> - -Change ap_scan value: -0 = no scanning, -1 = %wpa_supplicant requests scans and uses scan results to select the AP, -2 = %wpa_supplicant does not use scanning and just requests driver to -associate and take care of AP selection - - -\subsection ctrl_iface_INTERFACES INTERFACES - -List configured interfaces. - -\verbatim -wlan0 -eth0 -\endverbatim - -*/ diff --git a/contrib/wpa_supplicant/doc/docbook/Makefile b/contrib/wpa_supplicant/doc/docbook/Makefile deleted file mode 100644 index 15c019c960b2..000000000000 --- a/contrib/wpa_supplicant/doc/docbook/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -all: man html pdf - -FILES += wpa_background -FILES += wpa_cli -FILES += wpa_passphrase -FILES += wpa_supplicant.conf -FILES += wpa_supplicant - -man: - for i in $(FILES); do docbook2man $$i.sgml; done - -html: - for i in $(FILES); do docbook2html $$i.sgml && \ - mv index.html $$i.html; done - -pdf: - for i in $(FILES); do docbook2pdf $$i.sgml; done - - -clean: - rm -f wpa_background.8 wpa_cli.8 wpa_passphrase.8 wpa_supplicant.8 - rm -f wpa_supplicant.conf.5 - rm -f manpage.links manpage.refs - rm -f $(FILES:%=%.pdf) - rm -f $(FILES:%=%.html) diff --git a/contrib/wpa_supplicant/doc/docbook/wpa_background.8 b/contrib/wpa_supplicant/doc/docbook/wpa_background.8 deleted file mode 100644 index c62f5e067ae2..000000000000 --- a/contrib/wpa_supplicant/doc/docbook/wpa_background.8 +++ /dev/null @@ -1,84 +0,0 @@ -.\" This manpage has been automatically generated by docbook2man -.\" from a DocBook document. This tool can be found at: -.\" <http://shell.ipoline.com/~elmert/comp/docbook2X/> -.\" Please send any bug reports, improvements, comments, patches, -.\" etc. to Steve Cheng <steve@ggi-project.org>. -.TH "WPA_BACKGROUND" "8" "28 November 2008" "" "" - -.SH NAME -wpa_background \- Background information on Wi-Fi Protected Access and IEEE 802.11i -.SH "WPA" -.PP -The original security mechanism of IEEE 802.11 standard was -not designed to be strong and has proven to be insufficient for -most networks that require some kind of security. Task group I -(Security) of IEEE 802.11 working group -(http://www.ieee802.org/11/) has worked to address the flaws of -the base standard and has in practice completed its work in May -2004. The IEEE 802.11i amendment to the IEEE 802.11 standard was -approved in June 2004 and published in July 2004. -.PP -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<TM> (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). -.PP -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. -.PP -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). -.PP -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). -.PP -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). -.SH "IEEE 802.11I / WPA2" -.PP -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). -.SH "SEE ALSO" -.PP -\fBwpa_supplicant\fR(8) -.SH "LEGAL" -.PP -wpa_supplicant is copyright (c) 2003-2005, -Jouni Malinen <j@w1.fi> and -contributors. -All Rights Reserved. -.PP -This program is dual-licensed under both the GPL version 2 -and BSD license. Either license may be used at your option. diff --git a/contrib/wpa_supplicant/doc/docbook/wpa_background.sgml b/contrib/wpa_supplicant/doc/docbook/wpa_background.sgml deleted file mode 100644 index 91b08bc42d0d..000000000000 --- a/contrib/wpa_supplicant/doc/docbook/wpa_background.sgml +++ /dev/null @@ -1,101 +0,0 @@ -<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN"> - -<refentry> - <refmeta> - <refentrytitle>wpa_background</refentrytitle> - <manvolnum>8</manvolnum> - </refmeta> - <refnamediv> - <refname>wpa_background</refname> - <refpurpose>Background information on Wi-Fi Protected Access and IEEE 802.11i</refpurpose> - </refnamediv> - <refsect1> - <title>WPA</title> - - <para>The original security mechanism of IEEE 802.11 standard was - not designed to be strong and has proven to be insufficient for - most networks that require some kind of security. Task group I - (Security) of IEEE 802.11 working group - (http://www.ieee802.org/11/) has worked to address the flaws of - the base standard and has in practice completed its work in May - 2004. The IEEE 802.11i amendment to the IEEE 802.11 standard was - approved in June 2004 and published in July 2004.</para> - - <para>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<TM> (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).</para> - - <para>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.</para> - - <para>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).</para> - - <para>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).</para> - - <para>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).</para> - </refsect1> - - <refsect1> - <title>IEEE 802.11i / WPA2</title> - - <para>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).</para> - </refsect1> - - <refsect1> - <title>See Also</title> - <para> - <citerefentry> - <refentrytitle>wpa_supplicant</refentrytitle> - <manvolnum>8</manvolnum> - </citerefentry> - </para> - </refsect1> - - <refsect1> - <title>Legal</title> - <para>wpa_supplicant is copyright (c) 2003-2005, - Jouni Malinen <email>j@w1.fi</email> and - contributors. - All Rights Reserved.</para> - - <para>This program is dual-licensed under both the GPL version 2 - and BSD license. Either license may be used at your option.</para> - </refsect1> -</refentry> diff --git a/contrib/wpa_supplicant/doc/docbook/wpa_cli.8 b/contrib/wpa_supplicant/doc/docbook/wpa_cli.8 deleted file mode 100644 index 43cc43d72910..000000000000 --- a/contrib/wpa_supplicant/doc/docbook/wpa_cli.8 +++ /dev/null @@ -1,210 +0,0 @@ -.\" This manpage has been automatically generated by docbook2man -.\" from a DocBook document. This tool can be found at: -.\" <http://shell.ipoline.com/~elmert/comp/docbook2X/> -.\" Please send any bug reports, improvements, comments, patches, -.\" etc. to Steve Cheng <steve@ggi-project.org>. -.TH "WPA_CLI" "8" "28 November 2008" "" "" - -.SH NAME -wpa_cli \- WPA command line client -.SH SYNOPSIS - -\fBwpa_cli\fR [ \fB-p \fIpath to ctrl sockets\fB\fR ] [ \fB-i \fIifname\fB\fR ] [ \fB-hvB\fR ] [ \fB-a \fIaction file\fB\fR ] [ \fB-P \fIpid file\fB\fR ] [ \fB\fIcommand ...\fB\fR ] - -.SH "OVERVIEW" -.PP -wpa_cli is a text-based frontend program for interacting -with wpa_supplicant. It is used to query current status, change -configuration, trigger events, and request interactive user -input. -.PP -wpa_cli can show the current authentication status, selected -security mode, dot11 and dot1x MIBs, etc. In addition, it can -configure some variables like EAPOL state machine parameters and -trigger events like reassociation and IEEE 802.1X -logoff/logon. wpa_cli provides a user interface to request -authentication information, like username and password, if these -are not included in the configuration. This can be used to -implement, e.g., one-time-passwords or generic token card -authentication where the authentication is based on a -challenge-response that uses an external device for generating the -response. -.PP -The control interface of wpa_supplicant can be configured to -allow non-root user access (ctrl_interface_group in the -configuration file). This makes it possible to run wpa_cli with a -normal user account. -.PP -wpa_cli supports two modes: interactive and command -line. Both modes share the same command set and the main -difference is in interactive mode providing access to unsolicited -messages (event messages, username/password requests). -.PP -Interactive mode is started when wpa_cli is executed without -including the command as a command line parameter. Commands are -then entered on the wpa_cli prompt. In command line mode, the same -commands are entered as command line arguments for wpa_cli. -.SH "INTERACTIVE AUTHENTICATION PARAMETERS REQUEST" -.PP -When wpa_supplicant need authentication parameters, like -username and password, which are not present in the configuration -file, it sends a request message to all attached frontend programs, -e.g., wpa_cli in interactive mode. wpa_cli shows these requests -with "CTRL-REQ-<type>-<id>:<text>" -prefix. <type> is IDENTITY, PASSWORD, or OTP -(one-time-password). <id> is a unique identifier for the -current network. <text> is description of the request. In -case of OTP request, it includes the challenge from the -authentication server. -.PP -The reply to these requests can be given with -\fBidentity\fR, \fBpassword\fR, and -\fBotp\fR commands. <id> needs to be copied from -the matching request. \fBpassword\fR and -\fBotp\fR commands can be used regardless of whether -the request was for PASSWORD or OTP. The main difference between these -two commands is that values given with \fBpassword\fR are -remembered as long as wpa_supplicant is running whereas values given -with \fBotp\fR are used only once and then forgotten, -i.e., wpa_supplicant will ask frontend for a new value for every use. -This can be used to implement one-time-password lists and generic token -card -based authentication. -.PP -Example request for password and a matching reply: -.sp -.RS - -.nf -CTRL-REQ-PASSWORD-1:Password needed for SSID foobar -> password 1 mysecretpassword -.fi -.RE -.PP -Example request for generic token card challenge-response: -.sp -.RS - -.nf -CTRL-REQ-OTP-2:Challenge 1235663 needed for SSID foobar -> otp 2 9876 -.fi -.RE -.SH "COMMAND ARGUMENTS" -.TP -\fB-p path\fR -Change the path where control sockets should -be found. -.TP -\fB-i ifname\fR -Specify the interface that is being -configured. By default, choose the first interface found with -a control socket in the socket path. -.TP -\fB-h\fR -Help. Show a usage message. -.TP -\fB-v\fR -Show version information. -.TP -\fB-B\fR -Run as a daemon in the background. -.TP -\fB-a file\fR -Run in daemon mode executing the action file -based on events from wpa_supplicant. The specified file will -be executed with the first argument set to interface name and -second to "CONNECTED" or "DISCONNECTED" depending on the event. -This can be used to execute networking tools required to configure -the interface. - -Additionally, three environmental variables are available to -the file: WPA_CTRL_DIR, WPA_ID, and WPA_ID_STR. WPA_CTRL_DIR -contains the absolute path to the ctrl_interface socket. WPA_ID -contains the unique network_id identifier assigned to the active -network, and WPA_ID_STR contains the content of the id_str option. -.TP -\fB-P file\fR -Set the location of the PID -file. -.TP -\fBcommand\fR -Run a command. The available commands are -listed in the next section. -.SH "COMMANDS" -.PP -The following commands are available: -.TP -\fBstatus\fR -get current WPA/EAPOL/EAP status -.TP -\fBmib\fR -get MIB variables (dot1x, dot11) -.TP -\fBhelp\fR -show this usage help -.TP -\fBinterface [ifname]\fR -show interfaces/select interface -.TP -\fBlevel <debug level>\fR -change debug level -.TP -\fBlicense\fR -show full wpa_cli license -.TP -\fBlogoff\fR -IEEE 802.1X EAPOL state machine logoff -.TP -\fBlogon\fR -IEEE 802.1X EAPOL state machine logon -.TP -\fBset\fR -set variables (shows list of variables when run without arguments) -.TP -\fBpmksa\fR -show PMKSA cache -.TP -\fBreassociate\fR -force reassociation -.TP -\fBreconfigure\fR -force wpa_supplicant to re-read its configuration file -.TP -\fBpreauthenticate <BSSID>\fR -force preauthentication -.TP -\fBidentity <network id> <identity>\fR -configure identity for an SSID -.TP -\fBpassword <network id> <password>\fR -configure password for an SSID -.TP -\fBpin <network id> <pin>\fR -configure pin for an SSID -.TP -\fBotp <network id> <password>\fR -configure one-time-password for an SSID -.TP -\fBbssid <network id> <BSSID>\fR -set preferred BSSID for an SSID -.TP -\fBlist_networks\fR -list configured networks -.TP -\fBterminate\fR -terminate \fBwpa_supplicant\fR -.TP -\fBquit\fR -exit wpa_cli -.SH "SEE ALSO" -.PP -\fBwpa_supplicant\fR(8) -.SH "LEGAL" -.PP -wpa_supplicant is copyright (c) 2003-2005, -Jouni Malinen <j@w1.fi> and -contributors. -All Rights Reserved. -.PP -This program is dual-licensed under both the GPL version 2 -and BSD license. Either license may be used at your option. diff --git a/contrib/wpa_supplicant/doc/docbook/wpa_cli.sgml b/contrib/wpa_supplicant/doc/docbook/wpa_cli.sgml deleted file mode 100644 index ade036210e4c..000000000000 --- a/contrib/wpa_supplicant/doc/docbook/wpa_cli.sgml +++ /dev/null @@ -1,339 +0,0 @@ -<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN"> - -<refentry> - <refmeta> - <refentrytitle>wpa_cli</refentrytitle> - <manvolnum>8</manvolnum> - </refmeta> - <refnamediv> - <refname>wpa_cli</refname> - - <refpurpose>WPA command line client</refpurpose> - </refnamediv> - - <refsynopsisdiv> - <cmdsynopsis> - <command>wpa_cli</command> - <arg>-p <replaceable>path to ctrl sockets</replaceable></arg> - <arg>-i <replaceable>ifname</replaceable></arg> - <arg>-hvB</arg> - <arg>-a <replaceable>action file</replaceable></arg> - <arg>-P <replaceable>pid file</replaceable></arg> - <arg><replaceable>command ...</replaceable></arg> - </cmdsynopsis> - </refsynopsisdiv> - - <refsect1> - <title>Overview</title> - - <para>wpa_cli is a text-based frontend program for interacting - with wpa_supplicant. It is used to query current status, change - configuration, trigger events, and request interactive user - input.</para> - - <para>wpa_cli can show the current authentication status, selected - security mode, dot11 and dot1x MIBs, etc. In addition, it can - configure some variables like EAPOL state machine parameters and - trigger events like reassociation and IEEE 802.1X - logoff/logon. wpa_cli provides a user interface to request - authentication information, like username and password, if these - are not included in the configuration. This can be used to - implement, e.g., one-time-passwords or generic token card - authentication where the authentication is based on a - challenge-response that uses an external device for generating the - response.</para> - - <para>The control interface of wpa_supplicant can be configured to - allow non-root user access (ctrl_interface_group in the - configuration file). This makes it possible to run wpa_cli with a - normal user account.</para> - - <para>wpa_cli supports two modes: interactive and command - line. Both modes share the same command set and the main - difference is in interactive mode providing access to unsolicited - messages (event messages, username/password requests).</para> - - <para>Interactive mode is started when wpa_cli is executed without - including the command as a command line parameter. Commands are - then entered on the wpa_cli prompt. In command line mode, the same - commands are entered as command line arguments for wpa_cli.</para> - </refsect1> - <refsect1> - <title>Interactive authentication parameters request</title> - - <para>When wpa_supplicant need authentication parameters, like - username and password, which are not present in the configuration - file, it sends a request message to all attached frontend programs, - e.g., wpa_cli in interactive mode. wpa_cli shows these requests - with "CTRL-REQ-<type>-<id>:<text>" - prefix. <type> is IDENTITY, PASSWORD, or OTP - (one-time-password). <id> is a unique identifier for the - current network. <text> is description of the request. In - case of OTP request, it includes the challenge from the - authentication server.</para> - - <para>The reply to these requests can be given with - <emphasis>identity</emphasis>, <emphasis>password</emphasis>, and - <emphasis>otp</emphasis> commands. <id> needs to be copied from - the matching request. <emphasis>password</emphasis> and - <emphasis>otp</emphasis> commands can be used regardless of whether - the request was for PASSWORD or OTP. The main difference between these - two commands is that values given with <emphasis>password</emphasis> are - remembered as long as wpa_supplicant is running whereas values given - with <emphasis>otp</emphasis> are used only once and then forgotten, - i.e., wpa_supplicant will ask frontend for a new value for every use. - This can be used to implement one-time-password lists and generic token - card -based authentication.</para> - - <para>Example request for password and a matching reply:</para> - -<blockquote><programlisting> -CTRL-REQ-PASSWORD-1:Password needed for SSID foobar -> password 1 mysecretpassword -</programlisting></blockquote> - - <para>Example request for generic token card challenge-response:</para> - -<blockquote><programlisting> -CTRL-REQ-OTP-2:Challenge 1235663 needed for SSID foobar -> otp 2 9876 -</programlisting></blockquote> - - </refsect1> - <refsect1> - <title>Command Arguments</title> - <variablelist> - <varlistentry> - <term>-p path</term> - - <listitem><para>Change the path where control sockets should - be found.</para></listitem> - </varlistentry> - - <varlistentry> - <term>-i ifname</term> - - <listitem><para>Specify the interface that is being - configured. By default, choose the first interface found with - a control socket in the socket path.</para></listitem> - </varlistentry> - - <varlistentry> - <term>-h</term> - <listitem><para>Help. Show a usage message.</para></listitem> - </varlistentry> - - - <varlistentry> - <term>-v</term> - <listitem><para>Show version information.</para></listitem> - </varlistentry> - - - <varlistentry> - <term>-B</term> - <listitem><para>Run as a daemon in the background.</para></listitem> - </varlistentry> - - <varlistentry> - <term>-a file</term> - - <listitem><para>Run in daemon mode executing the action file - based on events from wpa_supplicant. The specified file will - be executed with the first argument set to interface name and - second to "CONNECTED" or "DISCONNECTED" depending on the event. - This can be used to execute networking tools required to configure - the interface.</para> - - <para>Additionally, three environmental variables are available to - the file: WPA_CTRL_DIR, WPA_ID, and WPA_ID_STR. WPA_CTRL_DIR - contains the absolute path to the ctrl_interface socket. WPA_ID - contains the unique network_id identifier assigned to the active - network, and WPA_ID_STR contains the content of the id_str option. - </para></listitem> - </varlistentry> - - <varlistentry> - <term>-P file</term> - - <listitem><para>Set the location of the PID - file.</para></listitem> - </varlistentry> - - <varlistentry> - <term>command</term> - - <listitem><para>Run a command. The available commands are - listed in the next section.</para></listitem> - - </varlistentry> - </variablelist> - </refsect1> - <refsect1> - <title>Commands</title> - <para>The following commands are available:</para> - - <variablelist> - <varlistentry> - <term>status</term> - <listitem> - <para>get current WPA/EAPOL/EAP status</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>mib</term> - <listitem> - <para>get MIB variables (dot1x, dot11)</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>help</term> - <listitem> - <para>show this usage help</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>interface [ifname]</term> - <listitem> - <para>show interfaces/select interface</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>level <debug level></term> - <listitem> - <para>change debug level</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>license</term> - <listitem> - <para>show full wpa_cli license</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>logoff</term> - <listitem> - <para>IEEE 802.1X EAPOL state machine logoff</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>logon</term> - <listitem> - <para>IEEE 802.1X EAPOL state machine logon</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>set</term> - <listitem> - <para>set variables (shows list of variables when run without arguments)</para> - </listitem> - </varlistentry> - <varlistentry> - <term>pmksa</term> - <listitem> - <para>show PMKSA cache</para> - </listitem> - </varlistentry> - <varlistentry> - <term>reassociate</term> - <listitem> - <para>force reassociation</para> - </listitem> - </varlistentry> - <varlistentry> - <term>reconfigure</term> - <listitem> - <para>force wpa_supplicant to re-read its configuration file</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>preauthenticate <BSSID></term> - <listitem> - <para>force preauthentication</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>identity <network id> <identity></term> - <listitem> - <para>configure identity for an SSID</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>password <network id> <password></term> - <listitem> - <para>configure password for an SSID</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>pin <network id> <pin></term> - <listitem> - <para>configure pin for an SSID</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>otp <network id> <password></term> - <listitem> - <para>configure one-time-password for an SSID</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>bssid <network id> <BSSID></term> - <listitem> - <para>set preferred BSSID for an SSID</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>list_networks</term> - <listitem> - <para>list configured networks</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>terminate</term> - <listitem> - <para>terminate <command>wpa_supplicant</command></para> - </listitem> - </varlistentry> - - <varlistentry> - <term>quit</term> - <listitem><para>exit wpa_cli</para></listitem> - </varlistentry> - </variablelist> - </refsect1> - <refsect1> - <title>See Also</title> - <para> - <citerefentry> - <refentrytitle>wpa_supplicant</refentrytitle> - <manvolnum>8</manvolnum> - </citerefentry> - </para> - </refsect1> - <refsect1> - <title>Legal</title> - <para>wpa_supplicant is copyright (c) 2003-2005, - Jouni Malinen <email>j@w1.fi</email> and - contributors. - All Rights Reserved.</para> - - <para>This program is dual-licensed under both the GPL version 2 - and BSD license. Either license may be used at your option.</para> - </refsect1> -</refentry> diff --git a/contrib/wpa_supplicant/doc/docbook/wpa_passphrase.8 b/contrib/wpa_supplicant/doc/docbook/wpa_passphrase.8 deleted file mode 100644 index 52faebba5666..000000000000 --- a/contrib/wpa_supplicant/doc/docbook/wpa_passphrase.8 +++ /dev/null @@ -1,40 +0,0 @@ -.\" This manpage has been automatically generated by docbook2man -.\" from a DocBook document. This tool can be found at: -.\" <http://shell.ipoline.com/~elmert/comp/docbook2X/> -.\" Please send any bug reports, improvements, comments, patches, -.\" etc. to Steve Cheng <steve@ggi-project.org>. -.TH "WPA_PASSPHRASE" "8" "28 November 2008" "" "" - -.SH NAME -wpa_passphrase \- Generate a WPA PSK from an ASCII passphrase for a SSID -.SH SYNOPSIS - -\fBwpa_passphrase\fR [ \fB\fIssid\fB\fR ] [ \fB\fIpassphrase\fB\fR ] - -.SH "OVERVIEW" -.PP -\fBwpa_passphrase\fR pre-computes PSK entries for -network configuration blocks of a -\fIwpa_supplicant.conf\fR file. An ASCII passphrase -and SSID are used to generate a 256-bit PSK. -.SH "OPTIONS" -.TP -\fBssid\fR -The SSID whose passphrase should be derived. -.TP -\fBpassphrase\fR -The passphrase to use. If not included on the command line, -passphrase will be read from standard input. -.SH "SEE ALSO" -.PP -\fBwpa_supplicant.conf\fR(5) -\fBwpa_supplicant\fR(8) -.SH "LEGAL" -.PP -wpa_supplicant is copyright (c) 2003-2005, -Jouni Malinen <j@w1.fi> and -contributors. -All Rights Reserved. -.PP -This program is dual-licensed under both the GPL version 2 -and BSD license. Either license may be used at your option. diff --git a/contrib/wpa_supplicant/doc/docbook/wpa_passphrase.sgml b/contrib/wpa_supplicant/doc/docbook/wpa_passphrase.sgml deleted file mode 100644 index eacb119ee382..000000000000 --- a/contrib/wpa_supplicant/doc/docbook/wpa_passphrase.sgml +++ /dev/null @@ -1,73 +0,0 @@ -<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN"> - -<refentry> - <refmeta> - <refentrytitle>wpa_passphrase</refentrytitle> - <manvolnum>8</manvolnum> - </refmeta> - <refnamediv> - <refname>wpa_passphrase</refname> - <refpurpose>Generate a WPA PSK from an ASCII passphrase for a SSID</refpurpose> - </refnamediv> - <refsynopsisdiv> - <cmdsynopsis> - <command>wpa_passphrase</command> - <arg><replaceable>ssid</replaceable></arg> - <arg><replaceable>passphrase</replaceable></arg> - </cmdsynopsis> - </refsynopsisdiv> - - <refsect1> - <title>Overview</title> - - <para><command>wpa_passphrase</command> pre-computes PSK entries for - network configuration blocks of a - <filename>wpa_supplicant.conf</filename> file. An ASCII passphrase - and SSID are used to generate a 256-bit PSK.</para> - </refsect1> - - <refsect1> - <title>Options</title> - <variablelist> - <varlistentry> - <term>ssid</term> - <listitem> - <para>The SSID whose passphrase should be derived.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>passphrase</term> - <listitem> - <para>The passphrase to use. If not included on the command line, - passphrase will be read from standard input.</para> - </listitem> - </varlistentry> - </variablelist> - </refsect1> - - <refsect1> - <title>See Also</title> - <para> - <citerefentry> - <refentrytitle>wpa_supplicant.conf</refentrytitle> - <manvolnum>5</manvolnum> - </citerefentry> - <citerefentry> - <refentrytitle>wpa_supplicant</refentrytitle> - <manvolnum>8</manvolnum> - </citerefentry> - </para> - - </refsect1> - <refsect1> - <title>Legal</title> - <para>wpa_supplicant is copyright (c) 2003-2005, - Jouni Malinen <email>j@w1.fi</email> and - contributors. - All Rights Reserved.</para> - - <para>This program is dual-licensed under both the GPL version 2 - and BSD license. Either license may be used at your option.</para> - </refsect1> -</refentry> diff --git a/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.8 b/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.8 deleted file mode 100644 index e7d8406413bb..000000000000 --- a/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.8 +++ /dev/null @@ -1,579 +0,0 @@ -.\" This manpage has been automatically generated by docbook2man -.\" from a DocBook document. This tool can be found at: -.\" <http://shell.ipoline.com/~elmert/comp/docbook2X/> -.\" Please send any bug reports, improvements, comments, patches, -.\" etc. to Steve Cheng <steve@ggi-project.org>. -.TH "WPA_SUPPLICANT" "8" "28 November 2008" "" "" - -.SH NAME -wpa_supplicant \- Wi-Fi Protected Access client and IEEE 802.1X supplicant -.SH SYNOPSIS - -\fBwpa_supplicant\fR [ \fB-BddfhKLqqtuvwW\fR ] [ \fB-i\fIifname\fB\fR ] [ \fB-c\fIconfig file\fB\fR ] [ \fB-D\fIdriver\fB\fR ] [ \fB-P\fIPID_file\fB\fR ] [ \fB-f\fIoutput file\fB\fR ] - -.SH "OVERVIEW" -.PP -Wireless networks do not require physical access to the network equipment -in the same way as wired networks. This makes it easier for unauthorized -users to passively monitor a network and capture all transmitted frames. -In addition, unauthorized use of the network is much easier. In many cases, -this can happen even without user's explicit knowledge since the wireless -LAN adapter may have been configured to automatically join any available -network. -.PP -Link-layer encryption can be used to provide a layer of security for -wireless networks. The original wireless LAN standard, IEEE 802.11, -included a simple encryption mechanism, WEP. However, that proved to -be flawed in many areas and network protected with WEP cannot be consider -secure. IEEE 802.1X authentication and frequently changed dynamic WEP keys -can be used to improve the network security, but even that has inherited -security issues due to the use of WEP for encryption. Wi-Fi Protected -Access and IEEE 802.11i amendment to the wireless LAN standard introduce -a much improvement mechanism for securing wireless networks. IEEE 802.11i -enabled networks that are using CCMP (encryption mechanism based on strong -cryptographic algorithm AES) can finally be called secure used for -applications which require efficient protection against unauthorized -access. -.PP -\fBwpa_supplicant\fR is an implementation of -the WPA Supplicant component, i.e., the part that runs in the -client stations. It implements WPA key negotiation with a WPA -Authenticator and EAP authentication with Authentication -Server. In addition, it controls the roaming and IEEE 802.11 -authentication/association of the wireless LAN driver. -.PP -\fBwpa_supplicant\fR is designed to be a -"daemon" program that runs in the background and acts as the -backend component controlling the wireless -connection. \fBwpa_supplicant\fR supports separate -frontend programs and an example text-based frontend, -\fBwpa_cli\fR, is included with -wpa_supplicant. -.PP -Before wpa_supplicant can do its work, the network interface -must be available. That means that the physical device must be -present and enabled, and the driver for the device must have be -loaded. Note, however, that the '-w' option of the wpa_supplicant -daemon instructs the daemon to continue running and to wait for -the interface to become available. Without the '-w' option, the -daemon will exit immediately if the device is not already -available. -.PP -After \fBwpa_supplicant\fR has configured the -network device, higher level configuration such as DHCP may -proceed. There are a variety of ways to integrate wpa_supplicant -into a machine's networking scripts, a few of which are described -in sections below. -.PP -The following steps are used when associating with an AP -using WPA: -.TP 0.2i -\(bu -\fBwpa_supplicant\fR requests the kernel -driver to scan neighboring BSSes -.TP 0.2i -\(bu -\fBwpa_supplicant\fR selects a BSS based on -its configuration -.TP 0.2i -\(bu -\fBwpa_supplicant\fR requests the kernel -driver to associate with the chosen BSS -.TP 0.2i -\(bu -If WPA-EAP: integrated IEEE 802.1X Supplicant or -external Xsupplicant completes EAP authentication with the -authentication server (proxied by the Authenticator in the -AP) -.TP 0.2i -\(bu -If WPA-EAP: master key is received from the IEEE 802.1X -Supplicant -.TP 0.2i -\(bu -If WPA-PSK: \fBwpa_supplicant\fR uses PSK -as the master session key -.TP 0.2i -\(bu -\fBwpa_supplicant\fR completes WPA 4-Way -Handshake and Group Key Handshake with the Authenticator -(AP) -.TP 0.2i -\(bu -\fBwpa_supplicant\fR configures encryption -keys for unicast and broadcast -.TP 0.2i -\(bu -normal data packets can be transmitted and received -.SH "SUPPORTED FEATURES" -.PP -Supported WPA/IEEE 802.11i features: -.TP 0.2i -\(bu -WPA-PSK ("WPA-Personal") -.TP 0.2i -\(bu -WPA with EAP (e.g., with RADIUS authentication server) -("WPA-Enterprise") Following authentication methods are -supported with an integrate IEEE 802.1X Supplicant: -.RS -.TP 0.2i -\(bu -EAP-TLS -.RE -.RS -.TP 0.2i -\(bu -EAP-PEAP/MSCHAPv2 (both PEAPv0 and PEAPv1) -.TP 0.2i -\(bu -EAP-PEAP/TLS (both PEAPv0 and PEAPv1) -.TP 0.2i -\(bu -EAP-PEAP/GTC (both PEAPv0 and PEAPv1) -.TP 0.2i -\(bu -EAP-PEAP/OTP (both PEAPv0 and PEAPv1) -.TP 0.2i -\(bu -EAP-PEAP/MD5-Challenge (both PEAPv0 and PEAPv1) -.TP 0.2i -\(bu -EAP-TTLS/EAP-MD5-Challenge -.TP 0.2i -\(bu -EAP-TTLS/EAP-GTC -.TP 0.2i -\(bu -EAP-TTLS/EAP-OTP -.TP 0.2i -\(bu -EAP-TTLS/EAP-MSCHAPv2 -.TP 0.2i -\(bu -EAP-TTLS/EAP-TLS -.TP 0.2i -\(bu -EAP-TTLS/MSCHAPv2 -.TP 0.2i -\(bu -EAP-TTLS/MSCHAP -.TP 0.2i -\(bu -EAP-TTLS/PAP -.TP 0.2i -\(bu -EAP-TTLS/CHAP -.TP 0.2i -\(bu -EAP-SIM -.TP 0.2i -\(bu -EAP-AKA -.TP 0.2i -\(bu -EAP-PSK -.TP 0.2i -\(bu -EAP-PAX -.TP 0.2i -\(bu -LEAP (note: requires special support from -the driver for IEEE 802.11 authentication) -.TP 0.2i -\(bu -(following methods are supported, but since -they do not generate keying material, they cannot be used -with WPA or IEEE 802.1X WEP keying) -.TP 0.2i -\(bu -EAP-MD5-Challenge -.TP 0.2i -\(bu -EAP-MSCHAPv2 -.TP 0.2i -\(bu -EAP-GTC -.TP 0.2i -\(bu -EAP-OTP -.RE -.TP 0.2i -\(bu -key management for CCMP, TKIP, WEP104, WEP40 -.TP 0.2i -\(bu -RSN/WPA2 (IEEE 802.11i) -.RS -.TP 0.2i -\(bu -pre-authentication -.TP 0.2i -\(bu -PMKSA caching -.RE -.SH "AVAILABLE DRIVERS" -.PP -A summary of available driver backends is below. Support for each -of the driver backends is chosen at wpa_supplicant compile time. For a -list of supported driver backends that may be used with the -D option on -your system, refer to the help output of wpa_supplicant -(\fBwpa_supplicant -h\fR). -.TP -\fBhostap\fR -(default) Host AP driver (Intersil Prism2/2.5/3). -(this can also be used with Linuxant DriverLoader). -.TP -\fBhermes\fR -Agere Systems Inc. driver (Hermes-I/Hermes-II). -.TP -\fBmadwifi\fR -MADWIFI 802.11 support (Atheros, etc.). -.TP -\fBatmel\fR -ATMEL AT76C5XXx (USB, PCMCIA). -.TP -\fBwext\fR -Linux wireless extensions (generic). -.TP -\fBndiswrapper\fR -Linux ndiswrapper. -.TP -\fBbroadcom\fR -Broadcom wl.o driver. -.TP -\fBipw\fR -Intel ipw2100/2200 driver. -.TP -\fBwired\fR -wpa_supplicant wired Ethernet driver -.TP -\fBbsd\fR -BSD 802.11 support (Atheros, etc.). -.TP -\fBndis\fR -Windows NDIS driver. -.SH "COMMAND LINE OPTIONS" -.PP -Most command line options have global scope. Some are given per -interface, and are only valid if at least one \fB-i\fR option -is specified, otherwise they're ignored. Option groups for different -interfaces must be separated by \fB-N\fR option. -.TP -\fB-b br_ifname\fR -Optional bridge interface name. (Per interface) -.TP -\fB-B\fR -Run daemon in the background. -.TP -\fB-i ifname\fR -Interface to listen on. Multiple instances of this option can -be present, one per interface, separated by \fB-N\fR -option (see below). -.TP -\fB-c filename\fR -Path to configuration file. (Per interface) -.TP -\fB-P PID_file\fR -Path to PID file. -.TP -\fB-C ctrl_interface\fR -Path to ctrl_interface socket (Per interface. Only used if -\fB-c\fR is not). -.TP -\fB-g global ctrl_interface\fR -Path to global ctrl_interface socket. If specified, interface -definitions may be omitted. -.TP -\fB-D driver\fR -Driver to use. (Per interface, see the available options -below.) -.TP -\fB-f output file\fR -Log output to specified file instead of stdout. -.TP -\fB-d\fR -Increase debugging verbosity (\fB-dd\fR even -more). -.TP -\fB-K\fR -Include keys (passwords, etc.) in debug output. -.TP -\fB-t\fR -Include timestamp in debug messages. -.TP -\fB-e\fR -Use external IEEE 802.1X Supplicant (e.g., -\fBxsupplicant\fR) (this disables the internal -Supplicant). -.TP -\fB-h\fR -Help. Show a usage message. -.TP -\fB-L\fR -Show license (GPL and BSD). -.TP -\fB-q\fR -Decrease debugging verbosity (\fB-qq\fR even -less). -.TP -\fB-u\fR -Enabled DBus control interface. If enabled, interface -definitions may be omitted. -.TP -\fB-v\fR -Show version. -.TP -\fB-w\fR -wait for interface to be added, if needed. normally, -\fBwpa_supplicant\fR will exit if the interface -is not there yet. -.TP -\fB-N\fR -Start describing new interface. -.SH "EXAMPLES" -.PP -In most common cases, \fBwpa_supplicant\fR is -started with: -.sp -.RS - -.nf -wpa_supplicant -Bw -c/etc/wpa_supplicant.conf -iwlan0 -.fi -.RE -.PP -This makes the process fork into background and wait for the wlan0 -interface if it is not available at startup time. -.PP -The easiest way to debug problems, and to get debug log for -bug reports, is to start \fBwpa_supplicant\fR on -foreground with debugging enabled: -.sp -.RS - -.nf -wpa_supplicant -c/etc/wpa_supplicant.conf -iwlan0 -d -.fi -.RE -.PP -\fBwpa_supplicant\fR can control multiple -interfaces (radios) either by running one process for each -interface separately or by running just one process and list of -options at command line. Each interface is separated with -N -argument. As an example, following command would start -wpa_supplicant for two interfaces: -.sp -.RS - -.nf -wpa_supplicant \\ - -c wpa1.conf -i wlan0 -D hostap -N \\ - -c wpa2.conf -i ath0 -D madwifi -.fi -.RE -.SH "OS REQUIREMENTS" -.PP -Current hardware/software requirements: -.TP 0.2i -\(bu -Linux kernel 2.4.x or 2.6.x with Linux Wireless -Extensions v15 or newer -.TP 0.2i -\(bu -FreeBSD 6-CURRENT -.TP 0.2i -\(bu -Microsoft Windows with WinPcap (at least WinXP, may work -with other versions) -.SH "SUPPORTED DRIVERS" -.TP -\fBHost AP driver for Prism2/2.5/3 (development snapshot/v0.2.x)\fR -(http://hostap.epitest.fi/) Driver needs to be set in -Managed mode (\fBiwconfig wlan0 mode managed\fR). -Please note that station firmware version needs to be 1.7.0 or -newer to work in WPA mode. -.TP -\fBLinuxant DriverLoader\fR -(http://www.linuxant.com/driverloader/) -with Windows NDIS driver for your wlan card supporting WPA. -.TP -\fBAgere Systems Inc. Linux Driver\fR -(http://www.agere.com/support/drivers/) Please note -that the driver interface file (driver_hermes.c) and hardware -specific include files are not included in the wpa_supplicant -distribution. You will need to copy these from the source -package of the Agere driver. -.TP -\fBmadwifi driver for cards based on Atheros chip set (ar521x)\fR -(http://sourceforge.net/projects/madwifi/) Please -note that you will need to modify the wpa_supplicant .config -file to use the correct path for the madwifi driver root -directory (CFLAGS += -I../madwifi/wpa line in example -defconfig). -.TP -\fBATMEL AT76C5XXx driver for USB and PCMCIA cards\fR -(http://atmelwlandriver.sourceforge.net/). -.TP -\fBLinux ndiswrapper\fR -(http://ndiswrapper.sourceforge.net/) with Windows -NDIS driver. -.TP -\fBBroadcom wl.o driver\fR -This is a generic Linux driver for Broadcom IEEE -802.11a/g cards. However, it is proprietary driver that is -not publicly available except for couple of exceptions, mainly -Broadcom-based APs/wireless routers that use Linux. The driver -binary can be downloaded, e.g., from Linksys support site -(http://www.linksys.com/support/gpl.asp) for Linksys -WRT54G. The GPL tarball includes cross-compiler and the needed -header file, wlioctl.h, for compiling wpa_supplicant. This -driver support in wpa_supplicant is expected to work also with -other devices based on Broadcom driver (assuming the driver -includes client mode support). -.TP -\fB Intel ipw2100 driver\fR -(http://sourceforge.net/projects/ipw2100/) -.TP -\fBIntel ipw2200 driver\fR -(http://sourceforge.net/projects/ipw2200/) -.TP -\fBLinux wireless extensions\fR -In theory, any driver that supports Linux wireless -extensions can be used with IEEE 802.1X (i.e., not WPA) when -using ap_scan=0 option in configuration file. -.TP -\fBWired Ethernet drivers\fR -Use ap_scan=0. -.TP -\fBBSD net80211 layer (e.g., Atheros driver)\fR -At the moment, this is for FreeBSD 6-CURRENT branch. -.TP -\fBWindows NDIS\fR -The current Windows port requires WinPcap -(http://winpcap.polito.it/). See README-Windows.txt for more -information. -.PP -wpa_supplicant was designed to be portable for different -drivers and operating systems. Hopefully, support for more wlan -cards and OSes will be added in the future. See developer.txt for -more information about the design of wpa_supplicant and porting to -other drivers. One main goal is to add full WPA/WPA2 support to -Linux wireless extensions to allow new drivers to be supported -without having to implement new driver-specific interface code in -wpa_supplicant. -.SH "ARCHITECTURE" -.PP -The -\fBwpa_supplicant\fR system consists of the following -components: -.TP -\fB\fIwpa_supplicant.conf\fB \fR -the configuration file describing all networks that the -user wants the computer to connect to. -.TP -\fBwpa_supplicant\fR -the program that directly interacts with the -network interface. -.TP -\fBwpa_cli\fR -the -client program that provides a high-level interface to the -functionality of the daemon. -.TP -\fBwpa_passphrase\fR -a utility needed to construct -\fIwpa_supplicant.conf\fR files that include -encrypted passwords. -.SH "QUICK START" -.PP -First, make a configuration file, e.g. -\fI/etc/wpa_supplicant.conf\fR, that describes the networks -you are interested in. See \fBwpa_supplicant.conf\fR(5) -for details. -.PP -Once the configuration is ready, you can test whether the -configuration works by running \fBwpa_supplicant\fR -with following command to start it on foreground with debugging -enabled: -.sp -.RS - -.nf -wpa_supplicant -iwlan0 -c/etc/wpa_supplicant.conf -d - -.fi -.RE -.PP -Assuming everything goes fine, you can start using following -command to start \fBwpa_supplicant\fR on background -without debugging: -.sp -.RS - -.nf -wpa_supplicant -iwlan0 -c/etc/wpa_supplicant.conf -B - -.fi -.RE -.PP -Please note that if you included more than one driver -interface in the build time configuration (.config), you may need -to specify which interface to use by including -D<driver -name> option on the command line. -.SH "INTERFACE TO PCMCIA-CS/CARDMRG" -.PP -For example, following small changes to pcmcia-cs scripts -can be used to enable WPA support: -.PP -Add MODE="Managed" and WPA="y" to the network scheme in -\fI/etc/pcmcia/wireless.opts\fR\&. -.PP -Add the following block to the end of \fBstart\fR -action handler in \fI/etc/pcmcia/wireless\fR: -.sp -.RS - -.nf -if [ "$WPA" = "y" -a -x /usr/local/bin/wpa_supplicant ]; then - /usr/local/bin/wpa_supplicant -Bw -c/etc/wpa_supplicant.conf -i$DEVICE -fi - -.fi -.RE -.PP -Add the following block to the end of \fBstop\fR -action handler (may need to be separated from other actions) in -\fI/etc/pcmcia/wireless\fR: -.sp -.RS - -.nf -if [ "$WPA" = "y" -a -x /usr/local/bin/wpa_supplicant ]; then - killall wpa_supplicant -fi - -.fi -.RE -.PP -This will make \fBcardmgr\fR start -\fBwpa_supplicant\fR when the card is plugged -in. \fBwpa_supplicant\fR will wait until the -interface is set up--either when a static IP address is configured -or when DHCP client is started--and will then negotiate keys with -the AP. -.SH "SEE ALSO" -.PP -\fBwpa_background\fR(8) -\fBwpa_supplicant.conf\fR(5) -\fBwpa_cli\fR(8) -\fBwpa_passphrase\fR(8) -.SH "LEGAL" -.PP -wpa_supplicant is copyright (c) 2003-2005, -Jouni Malinen <j@w1.fi> and -contributors. -All Rights Reserved. -.PP -This program is dual-licensed under both the GPL version 2 -and BSD license. Either license may be used at your option. diff --git a/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.conf.5 b/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.conf.5 deleted file mode 100644 index 494b8a21d1e5..000000000000 --- a/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.conf.5 +++ /dev/null @@ -1,230 +0,0 @@ -.\" This manpage has been automatically generated by docbook2man -.\" from a DocBook document. This tool can be found at: -.\" <http://shell.ipoline.com/~elmert/comp/docbook2X/> -.\" Please send any bug reports, improvements, comments, patches, -.\" etc. to Steve Cheng <steve@ggi-project.org>. -.TH "WPA_SUPPLICANT.CONF" "5" "28 November 2008" "" "" - -.SH NAME -wpa_supplicant.conf \- configuration file for wpa_supplicant -.SH "OVERVIEW" -.PP -\fBwpa_supplicant\fR is configured using a text -file that lists all accepted networks and security policies, -including pre-shared keys. See the example configuration file, -probably in \fB/usr/share/doc/wpa_supplicant/\fR, for -detailed information about the configuration format and supported -fields. -.PP -All file paths in this configuration file should use full -(absolute, not relative to working directory) path in order to allow -working directory to be changed. This can happen if wpa_supplicant is -run in the background. -.PP -Changes to configuration file can be reloaded be sending -SIGHUP signal to \fBwpa_supplicant\fR ('killall -HUP -wpa_supplicant'). Similarly, reloading can be triggered with -the \fBwpa_cli reconfigure\fR command. -.PP -Configuration file can include one or more network blocks, -e.g., one for each used SSID. wpa_supplicant will automatically -select the best network based on the order of network blocks in -the configuration file, network security level (WPA/WPA2 is -preferred), and signal strength. -.SH "QUICK EXAMPLES" -.TP 3 -1. -WPA-Personal (PSK) as home network and WPA-Enterprise with -EAP-TLS as work network. -.sp -.RS - -.nf -# allow frontend (e.g., wpa_cli) to be used by all users in 'wheel' group -ctrl_interface=/var/run/wpa_supplicant -ctrl_interface_group=wheel -# -# home network; allow all valid ciphers -network={ - ssid="home" - scan_ssid=1 - key_mgmt=WPA-PSK - psk="very secret passphrase" -} -# -# work network; use EAP-TLS with WPA; allow only CCMP and TKIP ciphers -network={ - ssid="work" - scan_ssid=1 - key_mgmt=WPA-EAP - pairwise=CCMP TKIP - group=CCMP TKIP - eap=TLS - identity="user@example.com" - ca_cert="/etc/cert/ca.pem" - client_cert="/etc/cert/user.pem" - private_key="/etc/cert/user.prv" - private_key_passwd="password" -} -.fi -.RE -.TP 3 -2. -WPA-RADIUS/EAP-PEAP/MSCHAPv2 with RADIUS servers that -use old peaplabel (e.g., Funk Odyssey and SBR, Meetinghouse -Aegis, Interlink RAD-Series) -.sp -.RS - -.nf -ctrl_interface=/var/run/wpa_supplicant -ctrl_interface_group=wheel -network={ - ssid="example" - scan_ssid=1 - key_mgmt=WPA-EAP - eap=PEAP - identity="user@example.com" - password="foobar" - ca_cert="/etc/cert/ca.pem" - phase1="peaplabel=0" - phase2="auth=MSCHAPV2" -} -.fi -.RE -.TP 3 -3. -EAP-TTLS/EAP-MD5-Challenge configuration with anonymous -identity for the unencrypted use. Real identity is sent only -within an encrypted TLS tunnel. -.sp -.RS - -.nf -ctrl_interface=/var/run/wpa_supplicant -ctrl_interface_group=wheel -network={ - ssid="example" - scan_ssid=1 - key_mgmt=WPA-EAP - eap=TTLS - identity="user@example.com" - anonymous_identity="anonymous@example.com" - password="foobar" - ca_cert="/etc/cert/ca.pem" - phase2="auth=MD5" -} -.fi -.RE -.TP 3 -4. -IEEE 802.1X (i.e., no WPA) with dynamic WEP keys -(require both unicast and broadcast); use EAP-TLS for -authentication -.sp -.RS - -.nf -ctrl_interface=/var/run/wpa_supplicant -ctrl_interface_group=wheel -network={ - ssid="1x-test" - scan_ssid=1 - key_mgmt=IEEE8021X - eap=TLS - identity="user@example.com" - ca_cert="/etc/cert/ca.pem" - client_cert="/etc/cert/user.pem" - private_key="/etc/cert/user.prv" - private_key_passwd="password" - eapol_flags=3 -} -.fi -.RE -.TP 3 -5. -Catch all example that allows more or less all -configuration modes. The configuration options are used based -on what security policy is used in the selected SSID. This is -mostly for testing and is not recommended for normal -use. -.sp -.RS - -.nf -ctrl_interface=/var/run/wpa_supplicant -ctrl_interface_group=wheel -network={ - ssid="example" - scan_ssid=1 - key_mgmt=WPA-EAP WPA-PSK IEEE8021X NONE - pairwise=CCMP TKIP - group=CCMP TKIP WEP104 WEP40 - psk="very secret passphrase" - eap=TTLS PEAP TLS - identity="user@example.com" - password="foobar" - ca_cert="/etc/cert/ca.pem" - client_cert="/etc/cert/user.pem" - private_key="/etc/cert/user.prv" - private_key_passwd="password" - phase1="peaplabel=0" - ca_cert2="/etc/cert/ca2.pem" - client_cert2="/etc/cer/user.pem" - private_key2="/etc/cer/user.prv" - private_key2_passwd="password" -} -.fi -.RE -.TP 3 -6. -Authentication for wired Ethernet. This can be used with -\fBwired\fR interface (-Dwired on command line). -.sp -.RS - -.nf -ctrl_interface=/var/run/wpa_supplicant -ctrl_interface_group=wheel -ap_scan=0 -network={ - key_mgmt=IEEE8021X - eap=MD5 - identity="user" - password="password" - eapol_flags=0 -} -.fi -.RE -.SH "CERTIFICATES" -.PP -Some EAP authentication methods require use of -certificates. EAP-TLS uses both server side and client -certificates whereas EAP-PEAP and EAP-TTLS only require the server -side certificate. When client certificate is used, a matching -private key file has to also be included in configuration. If the -private key uses a passphrase, this has to be configured in -wpa_supplicant.conf ("private_key_passwd"). -.PP -wpa_supplicant supports X.509 certificates in PEM and DER -formats. User certificate and private key can be included in the -same file. -.PP -If the user certificate and private key is received in -PKCS#12/PFX format, they need to be converted to suitable PEM/DER -format for wpa_supplicant. This can be done, e.g., with following -commands: -.sp -.RS - -.nf -# convert client certificate and private key to PEM format -openssl pkcs12 -in example.pfx -out user.pem -clcerts -# convert CA certificate (if included in PFX file) to PEM format -openssl pkcs12 -in example.pfx -out ca.pem -cacerts -nokeys -.fi -.RE -.SH "SEE ALSO" -.PP -\fBwpa_supplicant\fR(8) -\fBopenssl\fR(1) diff --git a/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.conf.sgml b/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.conf.sgml deleted file mode 100644 index 063e88298af5..000000000000 --- a/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.conf.sgml +++ /dev/null @@ -1,244 +0,0 @@ -<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN"> -<refentry> - <refmeta> - <refentrytitle>wpa_supplicant.conf</refentrytitle> - <manvolnum>5</manvolnum> - </refmeta> - <refnamediv> - <refname>wpa_supplicant.conf</refname> - <refpurpose>configuration file for wpa_supplicant</refpurpose> - </refnamediv> - <refsect1> - <title>Overview</title> - - <para><command>wpa_supplicant</command> is configured using a text - file that lists all accepted networks and security policies, - including pre-shared keys. See the example configuration file, - probably in <command>/usr/share/doc/wpa_supplicant/</command>, for - detailed information about the configuration format and supported - fields.</para> - - <para>All file paths in this configuration file should use full - (absolute, not relative to working directory) path in order to allow - working directory to be changed. This can happen if wpa_supplicant is - run in the background.</para> - - <para>Changes to configuration file can be reloaded be sending - SIGHUP signal to <command>wpa_supplicant</command> ('killall -HUP - wpa_supplicant'). Similarly, reloading can be triggered with - the <emphasis>wpa_cli reconfigure</emphasis> command.</para> - - <para>Configuration file can include one or more network blocks, - e.g., one for each used SSID. wpa_supplicant will automatically - select the best network based on the order of network blocks in - the configuration file, network security level (WPA/WPA2 is - preferred), and signal strength.</para> - </refsect1> - - <refsect1> - <title>Quick Examples</title> - - <orderedlist> - <listitem> - - <para>WPA-Personal (PSK) as home network and WPA-Enterprise with - EAP-TLS as work network.</para> - -<blockquote><programlisting> -# allow frontend (e.g., wpa_cli) to be used by all users in 'wheel' group -ctrl_interface=/var/run/wpa_supplicant -ctrl_interface_group=wheel -# -# home network; allow all valid ciphers -network={ - ssid="home" - scan_ssid=1 - key_mgmt=WPA-PSK - psk="very secret passphrase" -} -# -# work network; use EAP-TLS with WPA; allow only CCMP and TKIP ciphers -network={ - ssid="work" - scan_ssid=1 - key_mgmt=WPA-EAP - pairwise=CCMP TKIP - group=CCMP TKIP - eap=TLS - identity="user@example.com" - ca_cert="/etc/cert/ca.pem" - client_cert="/etc/cert/user.pem" - private_key="/etc/cert/user.prv" - private_key_passwd="password" -} -</programlisting></blockquote> - </listitem> - - <listitem> - <para>WPA-RADIUS/EAP-PEAP/MSCHAPv2 with RADIUS servers that - use old peaplabel (e.g., Funk Odyssey and SBR, Meetinghouse - Aegis, Interlink RAD-Series)</para> - -<blockquote><programlisting> -ctrl_interface=/var/run/wpa_supplicant -ctrl_interface_group=wheel -network={ - ssid="example" - scan_ssid=1 - key_mgmt=WPA-EAP - eap=PEAP - identity="user@example.com" - password="foobar" - ca_cert="/etc/cert/ca.pem" - phase1="peaplabel=0" - phase2="auth=MSCHAPV2" -} -</programlisting></blockquote> - </listitem> - - <listitem> - <para>EAP-TTLS/EAP-MD5-Challenge configuration with anonymous - identity for the unencrypted use. Real identity is sent only - within an encrypted TLS tunnel.</para> - - -<blockquote><programlisting> -ctrl_interface=/var/run/wpa_supplicant -ctrl_interface_group=wheel -network={ - ssid="example" - scan_ssid=1 - key_mgmt=WPA-EAP - eap=TTLS - identity="user@example.com" - anonymous_identity="anonymous@example.com" - password="foobar" - ca_cert="/etc/cert/ca.pem" - phase2="auth=MD5" -} -</programlisting></blockquote> - - </listitem> - - <listitem> - <para>IEEE 802.1X (i.e., no WPA) with dynamic WEP keys - (require both unicast and broadcast); use EAP-TLS for - authentication</para> - -<blockquote><programlisting> -ctrl_interface=/var/run/wpa_supplicant -ctrl_interface_group=wheel -network={ - ssid="1x-test" - scan_ssid=1 - key_mgmt=IEEE8021X - eap=TLS - identity="user@example.com" - ca_cert="/etc/cert/ca.pem" - client_cert="/etc/cert/user.pem" - private_key="/etc/cert/user.prv" - private_key_passwd="password" - eapol_flags=3 -} -</programlisting></blockquote> - </listitem> - - - <listitem> - <para>Catch all example that allows more or less all - configuration modes. The configuration options are used based - on what security policy is used in the selected SSID. This is - mostly for testing and is not recommended for normal - use.</para> - -<blockquote><programlisting> -ctrl_interface=/var/run/wpa_supplicant -ctrl_interface_group=wheel -network={ - ssid="example" - scan_ssid=1 - key_mgmt=WPA-EAP WPA-PSK IEEE8021X NONE - pairwise=CCMP TKIP - group=CCMP TKIP WEP104 WEP40 - psk="very secret passphrase" - eap=TTLS PEAP TLS - identity="user@example.com" - password="foobar" - ca_cert="/etc/cert/ca.pem" - client_cert="/etc/cert/user.pem" - private_key="/etc/cert/user.prv" - private_key_passwd="password" - phase1="peaplabel=0" - ca_cert2="/etc/cert/ca2.pem" - client_cert2="/etc/cer/user.pem" - private_key2="/etc/cer/user.prv" - private_key2_passwd="password" -} -</programlisting></blockquote> - </listitem> - - <listitem> - <para>Authentication for wired Ethernet. This can be used with - <emphasis>wired</emphasis> interface (-Dwired on command line).</para> - -<blockquote><programlisting> -ctrl_interface=/var/run/wpa_supplicant -ctrl_interface_group=wheel -ap_scan=0 -network={ - key_mgmt=IEEE8021X - eap=MD5 - identity="user" - password="password" - eapol_flags=0 -} -</programlisting></blockquote> - </listitem> - </orderedlist> - - - - - - </refsect1> - <refsect1> - <title>Certificates</title> - - <para>Some EAP authentication methods require use of - certificates. EAP-TLS uses both server side and client - certificates whereas EAP-PEAP and EAP-TTLS only require the server - side certificate. When client certificate is used, a matching - private key file has to also be included in configuration. If the - private key uses a passphrase, this has to be configured in - wpa_supplicant.conf ("private_key_passwd").</para> - - <para>wpa_supplicant supports X.509 certificates in PEM and DER - formats. User certificate and private key can be included in the - same file.</para> - - <para>If the user certificate and private key is received in - PKCS#12/PFX format, they need to be converted to suitable PEM/DER - format for wpa_supplicant. This can be done, e.g., with following - commands:</para> -<blockquote><programlisting> -# convert client certificate and private key to PEM format -openssl pkcs12 -in example.pfx -out user.pem -clcerts -# convert CA certificate (if included in PFX file) to PEM format -openssl pkcs12 -in example.pfx -out ca.pem -cacerts -nokeys -</programlisting></blockquote> - </refsect1> - - <refsect1> - <title>See Also</title> - <para> - <citerefentry> - <refentrytitle>wpa_supplicant</refentrytitle> - <manvolnum>8</manvolnum> - </citerefentry> - <citerefentry> - <refentrytitle>openssl</refentrytitle> - <manvolnum>1</manvolnum> - </citerefentry> - </para> - </refsect1> -</refentry> diff --git a/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.sgml b/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.sgml deleted file mode 100644 index ad570badd198..000000000000 --- a/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.sgml +++ /dev/null @@ -1,822 +0,0 @@ -<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN"> - -<refentry> - <refmeta> - <refentrytitle>wpa_supplicant</refentrytitle> - <manvolnum>8</manvolnum> - </refmeta> - <refnamediv> - <refname>wpa_supplicant</refname> - <refpurpose>Wi-Fi Protected Access client and IEEE 802.1X supplicant</refpurpose> - </refnamediv> - <refsynopsisdiv> - <cmdsynopsis> - <command>wpa_supplicant</command> - <arg>-BddfhKLqqtuvwW</arg> - <arg>-i<replaceable>ifname</replaceable></arg> - <arg>-c<replaceable>config file</replaceable></arg> - <arg>-D<replaceable>driver</replaceable></arg> - <arg>-P<replaceable>PID_file</replaceable></arg> - <arg>-f<replaceable>output file</replaceable></arg> - </cmdsynopsis> - </refsynopsisdiv> - <refsect1> - <title>Overview</title> - - <para> - Wireless networks do not require physical access to the network equipment - in the same way as wired networks. This makes it easier for unauthorized - users to passively monitor a network and capture all transmitted frames. - In addition, unauthorized use of the network is much easier. In many cases, - this can happen even without user's explicit knowledge since the wireless - LAN adapter may have been configured to automatically join any available - network. - </para> - - <para> - Link-layer encryption can be used to provide a layer of security for - wireless networks. The original wireless LAN standard, IEEE 802.11, - included a simple encryption mechanism, WEP. However, that proved to - be flawed in many areas and network protected with WEP cannot be consider - secure. IEEE 802.1X authentication and frequently changed dynamic WEP keys - can be used to improve the network security, but even that has inherited - security issues due to the use of WEP for encryption. Wi-Fi Protected - Access and IEEE 802.11i amendment to the wireless LAN standard introduce - a much improvement mechanism for securing wireless networks. IEEE 802.11i - enabled networks that are using CCMP (encryption mechanism based on strong - cryptographic algorithm AES) can finally be called secure used for - applications which require efficient protection against unauthorized - access. - </para> - - <para><command>wpa_supplicant</command> is an implementation of - the WPA Supplicant component, i.e., the part that runs in the - client stations. It implements WPA key negotiation with a WPA - Authenticator and EAP authentication with Authentication - Server. In addition, it controls the roaming and IEEE 802.11 - authentication/association of the wireless LAN driver.</para> - - <para><command>wpa_supplicant</command> is designed to be a - "daemon" program that runs in the background and acts as the - backend component controlling the wireless - connection. <command>wpa_supplicant</command> supports separate - frontend programs and an example text-based frontend, - <command>wpa_cli</command>, is included with - wpa_supplicant.</para> - - <para>Before wpa_supplicant can do its work, the network interface - must be available. That means that the physical device must be - present and enabled, and the driver for the device must have be - loaded. Note, however, that the '-w' option of the wpa_supplicant - daemon instructs the daemon to continue running and to wait for - the interface to become available. Without the '-w' option, the - daemon will exit immediately if the device is not already - available.</para> - - <para>After <command>wpa_supplicant</command> has configured the - network device, higher level configuration such as DHCP may - proceed. There are a variety of ways to integrate wpa_supplicant - into a machine's networking scripts, a few of which are described - in sections below.</para> - - <para>The following steps are used when associating with an AP - using WPA:</para> - - <itemizedlist> - <listitem> - <para><command>wpa_supplicant</command> requests the kernel - driver to scan neighboring BSSes</para> - </listitem> - - <listitem> - <para><command>wpa_supplicant</command> selects a BSS based on - its configuration</para> - </listitem> - - <listitem> - <para><command>wpa_supplicant</command> requests the kernel - driver to associate with the chosen BSS</para> - </listitem> - - <listitem> - <para>If WPA-EAP: integrated IEEE 802.1X Supplicant or - external Xsupplicant completes EAP authentication with the - authentication server (proxied by the Authenticator in the - AP)</para> - </listitem> - - <listitem> - <para>If WPA-EAP: master key is received from the IEEE 802.1X - Supplicant</para> - </listitem> - - <listitem> - <para>If WPA-PSK: <command>wpa_supplicant</command> uses PSK - as the master session key</para> - </listitem> - - <listitem> - <para><command>wpa_supplicant</command> completes WPA 4-Way - Handshake and Group Key Handshake with the Authenticator - (AP)</para> - </listitem> - - <listitem> - <para><command>wpa_supplicant</command> configures encryption - keys for unicast and broadcast</para> - </listitem> - - <listitem> - <para>normal data packets can be transmitted and received</para> - </listitem> - </itemizedlist> - </refsect1> - - <refsect1> - <title>Supported Features</title> - <para>Supported WPA/IEEE 802.11i features:</para> - <itemizedlist> - <listitem> - <para>WPA-PSK ("WPA-Personal")</para> - </listitem> - - <listitem> - <para>WPA with EAP (e.g., with RADIUS authentication server) - ("WPA-Enterprise") Following authentication methods are - supported with an integrate IEEE 802.1X Supplicant:</para> - - <itemizedlist> - <listitem> - <para>EAP-TLS</para> - </listitem> - </itemizedlist> - - <itemizedlist> - <listitem> - <para>EAP-PEAP/MSCHAPv2 (both PEAPv0 and PEAPv1)</para> - </listitem> - - - <listitem> - <para>EAP-PEAP/TLS (both PEAPv0 and PEAPv1)</para> - </listitem> - - <listitem> - <para>EAP-PEAP/GTC (both PEAPv0 and PEAPv1)</para> - </listitem> - - <listitem> - <para>EAP-PEAP/OTP (both PEAPv0 and PEAPv1)</para> - </listitem> - - <listitem> - <para>EAP-PEAP/MD5-Challenge (both PEAPv0 and PEAPv1)</para> - </listitem> - - <listitem> - <para>EAP-TTLS/EAP-MD5-Challenge</para> - </listitem> - - <listitem> - <para>EAP-TTLS/EAP-GTC</para> - </listitem> - - <listitem><para>EAP-TTLS/EAP-OTP</para></listitem> - - <listitem><para>EAP-TTLS/EAP-MSCHAPv2</para></listitem> - - <listitem><para>EAP-TTLS/EAP-TLS</para></listitem> - - <listitem><para>EAP-TTLS/MSCHAPv2</para></listitem> - - <listitem><para>EAP-TTLS/MSCHAP</para></listitem> - - <listitem><para>EAP-TTLS/PAP</para></listitem> - - <listitem><para>EAP-TTLS/CHAP</para></listitem> - - <listitem><para>EAP-SIM</para></listitem> - - <listitem><para>EAP-AKA</para></listitem> - - <listitem><para>EAP-PSK</para></listitem> - - <listitem><para>EAP-PAX</para></listitem> - - <listitem><para>LEAP (note: requires special support from - the driver for IEEE 802.11 authentication)</para></listitem> - - <listitem><para>(following methods are supported, but since - they do not generate keying material, they cannot be used - with WPA or IEEE 802.1X WEP keying)</para></listitem> - - <listitem><para>EAP-MD5-Challenge </para></listitem> - - <listitem><para>EAP-MSCHAPv2</para></listitem> - - <listitem><para>EAP-GTC</para></listitem> - - <listitem><para>EAP-OTP</para></listitem> - </itemizedlist> - </listitem> - - <listitem> - <para>key management for CCMP, TKIP, WEP104, WEP40</para> - </listitem> - - <listitem> - <para>RSN/WPA2 (IEEE 802.11i)</para> - <itemizedlist> - <listitem> - <para>pre-authentication</para> - </listitem> - - <listitem> - <para>PMKSA caching</para> - </listitem> - </itemizedlist> - </listitem> - </itemizedlist> - </refsect1> - - <refsect1> - <title>Available Drivers</title> - <para>A summary of available driver backends is below. Support for each - of the driver backends is chosen at wpa_supplicant compile time. For a - list of supported driver backends that may be used with the -D option on - your system, refer to the help output of wpa_supplicant - (<emphasis>wpa_supplicant -h</emphasis>).</para> - - <variablelist> - <varlistentry> - <term>hostap</term> - <listitem> - <para>(default) Host AP driver (Intersil Prism2/2.5/3). - (this can also be used with Linuxant DriverLoader).</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>hermes</term> - <listitem> - <para>Agere Systems Inc. driver (Hermes-I/Hermes-II).</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>madwifi</term> - <listitem> - <para>MADWIFI 802.11 support (Atheros, etc.).</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>atmel</term> - <listitem> - <para>ATMEL AT76C5XXx (USB, PCMCIA).</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>wext</term> - <listitem> - <para>Linux wireless extensions (generic).</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>ndiswrapper</term> - <listitem> - <para>Linux ndiswrapper.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>broadcom</term> - <listitem> - <para>Broadcom wl.o driver.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>ipw</term> - <listitem> - <para>Intel ipw2100/2200 driver.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>wired</term> - <listitem> - <para>wpa_supplicant wired Ethernet driver</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>bsd</term> - <listitem> - <para>BSD 802.11 support (Atheros, etc.).</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>ndis</term> - <listitem> - <para>Windows NDIS driver.</para> - </listitem> - </varlistentry> - </variablelist> - </refsect1> - - <refsect1> - <title>Command Line Options</title> - <para>Most command line options have global scope. Some are given per - interface, and are only valid if at least one <option>-i</option> option - is specified, otherwise they're ignored. Option groups for different - interfaces must be separated by <option>-N</option> option.</para> - <variablelist> - <varlistentry> - <term>-b br_ifname</term> - <listitem> - <para>Optional bridge interface name. (Per interface)</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-B</term> - <listitem> - <para>Run daemon in the background.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-i ifname</term> - <listitem> - <para>Interface to listen on. Multiple instances of this option can - be present, one per interface, separated by <option>-N</option> - option (see below).</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-c filename</term> - <listitem> - <para>Path to configuration file. (Per interface)</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-P PID_file</term> - <listitem> - <para>Path to PID file.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-C ctrl_interface</term> - <listitem> - <para>Path to ctrl_interface socket (Per interface. Only used if - <option>-c</option> is not).</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-g global ctrl_interface</term> - <listitem> - <para>Path to global ctrl_interface socket. If specified, interface - definitions may be omitted.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-D driver</term> - <listitem> - <para>Driver to use. (Per interface, see the available options - below.)</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-f output file</term> - <listitem> - <para>Log output to specified file instead of stdout.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-d</term> - <listitem> - <para>Increase debugging verbosity (<option>-dd</option> even - more).</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-K</term> - <listitem> - <para>Include keys (passwords, etc.) in debug output.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-t</term> - <listitem> - <para>Include timestamp in debug messages.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-e</term> - <listitem> - <para>Use external IEEE 802.1X Supplicant (e.g., - <command>xsupplicant</command>) (this disables the internal - Supplicant).</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-h</term> - <listitem> - <para>Help. Show a usage message.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-L</term> - <listitem> - <para>Show license (GPL and BSD).</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-q</term> - <listitem> - <para>Decrease debugging verbosity (<option>-qq</option> even - less).</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-u</term> - <listitem> - <para>Enabled DBus control interface. If enabled, interface - definitions may be omitted.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-v</term> - <listitem> - <para>Show version.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-w</term> - <listitem> - <para>wait for interface to be added, if needed. normally, - <command>wpa_supplicant</command> will exit if the interface - is not there yet.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>-N</term> - <listitem> - <para>Start describing new interface.</para> - </listitem> - </varlistentry> - </variablelist> - </refsect1> - - <refsect1> - <title>Examples</title> - - <para>In most common cases, <command>wpa_supplicant</command> is - started with:</para> - -<blockquote><programlisting> -wpa_supplicant -Bw -c/etc/wpa_supplicant.conf -iwlan0 -</programlisting></blockquote> - - <para>This makes the process fork into background and wait for the wlan0 - interface if it is not available at startup time.</para> - - <para>The easiest way to debug problems, and to get debug log for - bug reports, is to start <command>wpa_supplicant</command> on - foreground with debugging enabled:</para> - -<blockquote><programlisting> -wpa_supplicant -c/etc/wpa_supplicant.conf -iwlan0 -d -</programlisting></blockquote> - - <para><command>wpa_supplicant</command> can control multiple - interfaces (radios) either by running one process for each - interface separately or by running just one process and list of - options at command line. Each interface is separated with -N - argument. As an example, following command would start - wpa_supplicant for two interfaces:</para> - -<blockquote><programlisting> -wpa_supplicant \ - -c wpa1.conf -i wlan0 -D hostap -N \ - -c wpa2.conf -i ath0 -D madwifi -</programlisting></blockquote> - </refsect1> - - <refsect1> - <title>OS Requirements</title> - <para>Current hardware/software requirements:</para> - - <itemizedlist> - <listitem> - <para>Linux kernel 2.4.x or 2.6.x with Linux Wireless - Extensions v15 or newer</para> - </listitem> - - - <listitem> - <para>FreeBSD 6-CURRENT</para> - </listitem> - - <listitem> - <para>Microsoft Windows with WinPcap (at least WinXP, may work - with other versions)</para> - </listitem> - </itemizedlist> - </refsect1> - - <refsect1> - <title>Supported Drivers</title> - <variablelist> - <varlistentry> - <term>Host AP driver for Prism2/2.5/3 (development - snapshot/v0.2.x)</term> - <listitem> - <para> (http://hostap.epitest.fi/) Driver needs to be set in - Managed mode (<emphasis>iwconfig wlan0 mode managed</emphasis>). - Please note that station firmware version needs to be 1.7.0 or - newer to work in WPA mode.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>Linuxant DriverLoader</term> - <listitem> - <para>(http://www.linuxant.com/driverloader/) - with Windows NDIS driver for your wlan card supporting WPA.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>Agere Systems Inc. Linux Driver</term> - <listitem> - <para> (http://www.agere.com/support/drivers/) Please note - that the driver interface file (driver_hermes.c) and hardware - specific include files are not included in the wpa_supplicant - distribution. You will need to copy these from the source - package of the Agere driver.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>madwifi driver for cards based on Atheros chip set (ar521x)</term> - <listitem> - <para> (http://sourceforge.net/projects/madwifi/) Please - note that you will need to modify the wpa_supplicant .config - file to use the correct path for the madwifi driver root - directory (CFLAGS += -I../madwifi/wpa line in example - defconfig).</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>ATMEL AT76C5XXx driver for USB and PCMCIA cards</term> - <listitem> - <para> (http://atmelwlandriver.sourceforge.net/).</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>Linux ndiswrapper</term> - <listitem> - <para> (http://ndiswrapper.sourceforge.net/) with Windows - NDIS driver.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>Broadcom wl.o driver</term> - <listitem> - <para> This is a generic Linux driver for Broadcom IEEE - 802.11a/g cards. However, it is proprietary driver that is - not publicly available except for couple of exceptions, mainly - Broadcom-based APs/wireless routers that use Linux. The driver - binary can be downloaded, e.g., from Linksys support site - (http://www.linksys.com/support/gpl.asp) for Linksys - WRT54G. The GPL tarball includes cross-compiler and the needed - header file, wlioctl.h, for compiling wpa_supplicant. This - driver support in wpa_supplicant is expected to work also with - other devices based on Broadcom driver (assuming the driver - includes client mode support).</para> - </listitem> - </varlistentry> - - <varlistentry> - <term> Intel ipw2100 driver</term> - <listitem> - <para> (http://sourceforge.net/projects/ipw2100/)</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>Intel ipw2200 driver</term> - <listitem> - <para> (http://sourceforge.net/projects/ipw2200/)</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>Linux wireless extensions</term> - <listitem> - <para>In theory, any driver that supports Linux wireless - extensions can be used with IEEE 802.1X (i.e., not WPA) when - using ap_scan=0 option in configuration file.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>Wired Ethernet drivers</term> - <listitem> - <para>Use ap_scan=0.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>BSD net80211 layer (e.g., Atheros driver)</term> - <listitem> - <para>At the moment, this is for FreeBSD 6-CURRENT branch.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>Windows NDIS</term> - <listitem> - <para>The current Windows port requires WinPcap - (http://winpcap.polito.it/). See README-Windows.txt for more - information.</para> - </listitem> - </varlistentry> - </variablelist> - - - <para>wpa_supplicant was designed to be portable for different - drivers and operating systems. Hopefully, support for more wlan - cards and OSes will be added in the future. See developer.txt for - more information about the design of wpa_supplicant and porting to - other drivers. One main goal is to add full WPA/WPA2 support to - Linux wireless extensions to allow new drivers to be supported - without having to implement new driver-specific interface code in - wpa_supplicant.</para> - </refsect1> - - <refsect1> - <title>Architecture</title> <para>The - <command>wpa_supplicant</command> system consists of the following - components:</para> - - <variablelist> - <varlistentry> - <term><filename>wpa_supplicant.conf</filename> </term> - <listitem> - <para>the configuration file describing all networks that the - user wants the computer to connect to. </para> - </listitem> - </varlistentry> - <varlistentry> - <term><command>wpa_supplicant</command></term> - <listitem><para>the program that directly interacts with the - network interface. </para></listitem> - </varlistentry> - <varlistentry> - <term><command>wpa_cli</command></term> <listitem><para> the - client program that provides a high-level interface to the - functionality of the daemon. </para></listitem> - </varlistentry> - <varlistentry> - <term><command>wpa_passphrase</command></term> - <listitem><para>a utility needed to construct - <filename>wpa_supplicant.conf</filename> files that include - encrypted passwords.</para></listitem> - </varlistentry> - </variablelist> - </refsect1> - - <refsect1> - <title>Quick Start</title> - - <para>First, make a configuration file, e.g. - <filename>/etc/wpa_supplicant.conf</filename>, that describes the networks - you are interested in. See <citerefentry> - <refentrytitle>wpa_supplicant.conf</refentrytitle> - <manvolnum>5</manvolnum> - </citerefentry> - for details.</para> - - <para>Once the configuration is ready, you can test whether the - configuration works by running <command>wpa_supplicant</command> - with following command to start it on foreground with debugging - enabled:</para> - - <blockquote><programlisting> -wpa_supplicant -iwlan0 -c/etc/wpa_supplicant.conf -d - </programlisting></blockquote> - - <para>Assuming everything goes fine, you can start using following - command to start <command>wpa_supplicant</command> on background - without debugging:</para> - - <blockquote><programlisting> -wpa_supplicant -iwlan0 -c/etc/wpa_supplicant.conf -B - </programlisting></blockquote> - - <para>Please note that if you included more than one driver - interface in the build time configuration (.config), you may need - to specify which interface to use by including -D<driver - name> option on the command line.</para> - - <!-- XXX at this point, the page could include a little script - based on wpa_cli to wait for a connection and then run - dhclient --> - - </refsect1> - - <refsect1> - <title>Interface to pcmcia-cs/cardmrg</title> - - <para>For example, following small changes to pcmcia-cs scripts - can be used to enable WPA support:</para> - - <para>Add MODE="Managed" and WPA="y" to the network scheme in - <filename>/etc/pcmcia/wireless.opts</filename>.</para> - - <para>Add the following block to the end of <emphasis>start</emphasis> - action handler in <filename>/etc/pcmcia/wireless</filename>:</para> - - <blockquote><programlisting> -if [ "$WPA" = "y" -a -x /usr/local/bin/wpa_supplicant ]; then - /usr/local/bin/wpa_supplicant -Bw -c/etc/wpa_supplicant.conf -i$DEVICE -fi - </programlisting></blockquote> - - - <para>Add the following block to the end of <emphasis>stop</emphasis> - action handler (may need to be separated from other actions) in - <filename>/etc/pcmcia/wireless</filename>:</para> - - <blockquote><programlisting> -if [ "$WPA" = "y" -a -x /usr/local/bin/wpa_supplicant ]; then - killall wpa_supplicant -fi - </programlisting></blockquote> - - <para>This will make <command>cardmgr</command> start - <command>wpa_supplicant</command> when the card is plugged - in. <command>wpa_supplicant</command> will wait until the - interface is set up--either when a static IP address is configured - or when DHCP client is started--and will then negotiate keys with - the AP.</para> - </refsect1> - - <refsect1> - <title>See Also</title> - <para> - <citerefentry> - <refentrytitle>wpa_background</refentrytitle> - <manvolnum>8</manvolnum> - </citerefentry> - <citerefentry> - <refentrytitle>wpa_supplicant.conf</refentrytitle> - <manvolnum>5</manvolnum> - </citerefentry> - <citerefentry> - <refentrytitle>wpa_cli</refentrytitle> - <manvolnum>8</manvolnum> - </citerefentry> - <citerefentry> - <refentrytitle>wpa_passphrase</refentrytitle> - <manvolnum>8</manvolnum> - </citerefentry> - </para> - </refsect1> - <refsect1> - <title>Legal</title> - <para>wpa_supplicant is copyright (c) 2003-2005, - Jouni Malinen <email>j@w1.fi</email> and - contributors. - All Rights Reserved.</para> - - <para>This program is dual-licensed under both the GPL version 2 - and BSD license. Either license may be used at your option.</para> - </refsect1> -</refentry> diff --git a/contrib/wpa_supplicant/doc/doxygen.fast b/contrib/wpa_supplicant/doc/doxygen.fast deleted file mode 100644 index 597fd372c60c..000000000000 --- a/contrib/wpa_supplicant/doc/doxygen.fast +++ /dev/null @@ -1,243 +0,0 @@ -# Doxyfile 1.4.1 - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- -PROJECT_NAME = wpa_supplicant -PROJECT_NUMBER = 0.5.x -OUTPUT_DIRECTORY = doc -CREATE_SUBDIRS = NO -OUTPUT_LANGUAGE = English -USE_WINDOWS_ENCODING = NO -BRIEF_MEMBER_DESC = YES -REPEAT_BRIEF = YES -ABBREVIATE_BRIEF = "The $name class" \ - "The $name widget" \ - "The $name file" \ - is \ - provides \ - specifies \ - contains \ - represents \ - a \ - an \ - the -ALWAYS_DETAILED_SEC = NO -INLINE_INHERITED_MEMB = NO -FULL_PATH_NAMES = YES -STRIP_FROM_PATH = -STRIP_FROM_INC_PATH = -SHORT_NAMES = NO -JAVADOC_AUTOBRIEF = NO -MULTILINE_CPP_IS_BRIEF = NO -DETAILS_AT_TOP = NO -INHERIT_DOCS = YES -DISTRIBUTE_GROUP_DOC = NO -TAB_SIZE = 8 -ALIASES = -OPTIMIZE_OUTPUT_FOR_C = YES -OPTIMIZE_OUTPUT_JAVA = NO -SUBGROUPING = YES -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- -EXTRACT_ALL = NO -EXTRACT_PRIVATE = NO -EXTRACT_STATIC = NO -EXTRACT_LOCAL_CLASSES = YES -EXTRACT_LOCAL_METHODS = NO -HIDE_UNDOC_MEMBERS = NO -HIDE_UNDOC_CLASSES = NO -HIDE_FRIEND_COMPOUNDS = NO -HIDE_IN_BODY_DOCS = NO -INTERNAL_DOCS = NO -CASE_SENSE_NAMES = YES -HIDE_SCOPE_NAMES = NO -SHOW_INCLUDE_FILES = YES -INLINE_INFO = YES -SORT_MEMBER_DOCS = YES -SORT_BRIEF_DOCS = NO -SORT_BY_SCOPE_NAME = NO -GENERATE_TODOLIST = YES -GENERATE_TESTLIST = YES -GENERATE_BUGLIST = YES -GENERATE_DEPRECATEDLIST= YES -ENABLED_SECTIONS = -MAX_INITIALIZER_LINES = 30 -SHOW_USED_FILES = YES -SHOW_DIRECTORIES = NO -FILE_VERSION_FILTER = -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- -QUIET = NO -WARNINGS = YES -WARN_IF_UNDOCUMENTED = YES -WARN_IF_DOC_ERROR = YES -WARN_NO_PARAMDOC = YES -WARN_FORMAT = "$file:$line: $text" -WARN_LOGFILE = -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- -INPUT = . \ - ../hostapd/aes.c \ - ../hostapd/rc4.c \ - ../hostapd/rc4.h \ - ../hostapd/md5.c \ - ../hostapd/md5.h \ - ../hostapd/sha1.c \ - ../hostapd/sha1.h \ - ../hostapd/common.c \ - ../hostapd/common.h \ - ../hostapd/eloop.c \ - ../hostapd/eloop.h \ - ../hostapd/aes_wrap.c \ - ../hostapd/aes_wrap.h -FILE_PATTERNS = *.c *.h *.doxygen -RECURSIVE = YES -EXCLUDE = -EXCLUDE_SYMLINKS = NO -EXCLUDE_PATTERNS = -EXAMPLE_PATH = -EXAMPLE_PATTERNS = * -EXAMPLE_RECURSIVE = NO -IMAGE_PATH = doc -INPUT_FILTER = kerneldoc2doxygen.pl -FILTER_PATTERNS = -FILTER_SOURCE_FILES = YES -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- -SOURCE_BROWSER = YES -INLINE_SOURCES = NO -STRIP_CODE_COMMENTS = YES -REFERENCED_BY_RELATION = NO -REFERENCES_RELATION = NO -VERBATIM_HEADERS = NO -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- -ALPHABETICAL_INDEX = YES -COLS_IN_ALPHA_INDEX = 3 -IGNORE_PREFIX = -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- -GENERATE_HTML = YES -HTML_OUTPUT = html -HTML_FILE_EXTENSION = .html -HTML_HEADER = -HTML_FOOTER = -HTML_STYLESHEET = -HTML_ALIGN_MEMBERS = YES -GENERATE_HTMLHELP = NO -CHM_FILE = -HHC_LOCATION = -GENERATE_CHI = NO -BINARY_TOC = NO -TOC_EXPAND = NO -DISABLE_INDEX = NO -ENUM_VALUES_PER_LINE = 4 -GENERATE_TREEVIEW = NO -TREEVIEW_WIDTH = 250 -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- -GENERATE_LATEX = NO -LATEX_OUTPUT = latex -LATEX_CMD_NAME = latex -MAKEINDEX_CMD_NAME = makeindex -COMPACT_LATEX = NO -PAPER_TYPE = a4wide -EXTRA_PACKAGES = -LATEX_HEADER = -PDF_HYPERLINKS = YES -USE_PDFLATEX = YES -LATEX_BATCHMODE = NO -LATEX_HIDE_INDICES = NO -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- -GENERATE_RTF = NO -RTF_OUTPUT = rtf -COMPACT_RTF = NO -RTF_HYPERLINKS = NO -RTF_STYLESHEET_FILE = -RTF_EXTENSIONS_FILE = -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- -GENERATE_MAN = NO -MAN_OUTPUT = man -MAN_EXTENSION = .3 -MAN_LINKS = NO -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- -GENERATE_XML = NO -XML_OUTPUT = xml -XML_SCHEMA = -XML_DTD = -XML_PROGRAMLISTING = YES -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- -GENERATE_AUTOGEN_DEF = NO -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- -GENERATE_PERLMOD = NO -PERLMOD_LATEX = NO -PERLMOD_PRETTY = YES -PERLMOD_MAKEVAR_PREFIX = -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- -ENABLE_PREPROCESSING = YES -MACRO_EXPANSION = NO -EXPAND_ONLY_PREDEF = NO -SEARCH_INCLUDES = YES -INCLUDE_PATH = -INCLUDE_FILE_PATTERNS = -PREDEFINED = IEEE8021X_EAPOL -EXPAND_AS_DEFINED = -SKIP_FUNCTION_MACROS = YES -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- -TAGFILES = -GENERATE_TAGFILE = -ALLEXTERNALS = NO -EXTERNAL_GROUPS = YES -PERL_PATH = /usr/bin/perl -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- -CLASS_DIAGRAMS = NO -HIDE_UNDOC_RELATIONS = YES -HAVE_DOT = NO -CLASS_GRAPH = YES -COLLABORATION_GRAPH = YES -GROUP_GRAPHS = YES -UML_LOOK = NO -TEMPLATE_RELATIONS = NO -INCLUDE_GRAPH = YES -INCLUDED_BY_GRAPH = YES -CALL_GRAPH = YES -GRAPHICAL_HIERARCHY = YES -DIRECTORY_GRAPH = NO -DOT_IMAGE_FORMAT = png -DOT_PATH = -DOTFILE_DIRS = -MAX_DOT_GRAPH_WIDTH = 1024 -MAX_DOT_GRAPH_HEIGHT = 1024 -MAX_DOT_GRAPH_DEPTH = 1000 -DOT_TRANSPARENT = NO -DOT_MULTI_TARGETS = NO -GENERATE_LEGEND = YES -DOT_CLEANUP = YES -#--------------------------------------------------------------------------- -# Configuration::additions related to the search engine -#--------------------------------------------------------------------------- -SEARCHENGINE = NO diff --git a/contrib/wpa_supplicant/doc/doxygen.full b/contrib/wpa_supplicant/doc/doxygen.full deleted file mode 100644 index 9ed2ef845afb..000000000000 --- a/contrib/wpa_supplicant/doc/doxygen.full +++ /dev/null @@ -1,230 +0,0 @@ -# Doxyfile 1.4.1 - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- -PROJECT_NAME = wpa_supplicant -PROJECT_NUMBER = 0.5.x -OUTPUT_DIRECTORY = doc -CREATE_SUBDIRS = NO -OUTPUT_LANGUAGE = English -USE_WINDOWS_ENCODING = NO -BRIEF_MEMBER_DESC = YES -REPEAT_BRIEF = YES -ABBREVIATE_BRIEF = "The $name class" \ - "The $name widget" \ - "The $name file" \ - is \ - provides \ - specifies \ - contains \ - represents \ - a \ - an \ - the -ALWAYS_DETAILED_SEC = NO -INLINE_INHERITED_MEMB = NO -FULL_PATH_NAMES = YES -STRIP_FROM_PATH = -STRIP_FROM_INC_PATH = -SHORT_NAMES = NO -JAVADOC_AUTOBRIEF = NO -MULTILINE_CPP_IS_BRIEF = NO -DETAILS_AT_TOP = NO -INHERIT_DOCS = YES -DISTRIBUTE_GROUP_DOC = NO -TAB_SIZE = 8 -ALIASES = -OPTIMIZE_OUTPUT_FOR_C = YES -OPTIMIZE_OUTPUT_JAVA = NO -SUBGROUPING = YES -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- -EXTRACT_ALL = NO -EXTRACT_PRIVATE = NO -EXTRACT_STATIC = NO -EXTRACT_LOCAL_CLASSES = YES -EXTRACT_LOCAL_METHODS = NO -HIDE_UNDOC_MEMBERS = NO -HIDE_UNDOC_CLASSES = NO -HIDE_FRIEND_COMPOUNDS = NO -HIDE_IN_BODY_DOCS = NO -INTERNAL_DOCS = NO -CASE_SENSE_NAMES = YES -HIDE_SCOPE_NAMES = NO -SHOW_INCLUDE_FILES = YES -INLINE_INFO = YES -SORT_MEMBER_DOCS = YES -SORT_BRIEF_DOCS = NO -SORT_BY_SCOPE_NAME = NO -GENERATE_TODOLIST = YES -GENERATE_TESTLIST = YES -GENERATE_BUGLIST = YES -GENERATE_DEPRECATEDLIST= YES -ENABLED_SECTIONS = -MAX_INITIALIZER_LINES = 30 -SHOW_USED_FILES = YES -SHOW_DIRECTORIES = NO -FILE_VERSION_FILTER = -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- -QUIET = NO -WARNINGS = YES -WARN_IF_UNDOCUMENTED = YES -WARN_IF_DOC_ERROR = YES -WARN_NO_PARAMDOC = YES -WARN_FORMAT = "$file:$line: $text" -WARN_LOGFILE = -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- -INPUT = . -FILE_PATTERNS = *.c *.h *.doxygen -RECURSIVE = YES -EXCLUDE = -EXCLUDE_SYMLINKS = NO -EXCLUDE_PATTERNS = -EXAMPLE_PATH = -EXAMPLE_PATTERNS = * -EXAMPLE_RECURSIVE = NO -IMAGE_PATH = doc -INPUT_FILTER = kerneldoc2doxygen.pl -FILTER_PATTERNS = -FILTER_SOURCE_FILES = YES -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- -SOURCE_BROWSER = YES -INLINE_SOURCES = NO -STRIP_CODE_COMMENTS = YES -REFERENCED_BY_RELATION = NO -REFERENCES_RELATION = NO -VERBATIM_HEADERS = NO -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- -ALPHABETICAL_INDEX = YES -COLS_IN_ALPHA_INDEX = 3 -IGNORE_PREFIX = -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- -GENERATE_HTML = YES -HTML_OUTPUT = html -HTML_FILE_EXTENSION = .html -HTML_HEADER = -HTML_FOOTER = -HTML_STYLESHEET = -HTML_ALIGN_MEMBERS = YES -GENERATE_HTMLHELP = NO -CHM_FILE = -HHC_LOCATION = -GENERATE_CHI = NO -BINARY_TOC = NO -TOC_EXPAND = NO -DISABLE_INDEX = NO -ENUM_VALUES_PER_LINE = 4 -GENERATE_TREEVIEW = NO -TREEVIEW_WIDTH = 250 -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- -GENERATE_LATEX = YES -LATEX_OUTPUT = latex -LATEX_CMD_NAME = latex -MAKEINDEX_CMD_NAME = makeindex -COMPACT_LATEX = NO -PAPER_TYPE = a4wide -EXTRA_PACKAGES = -LATEX_HEADER = -PDF_HYPERLINKS = YES -USE_PDFLATEX = YES -LATEX_BATCHMODE = NO -LATEX_HIDE_INDICES = NO -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- -GENERATE_RTF = NO -RTF_OUTPUT = rtf -COMPACT_RTF = NO -RTF_HYPERLINKS = NO -RTF_STYLESHEET_FILE = -RTF_EXTENSIONS_FILE = -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- -GENERATE_MAN = NO -MAN_OUTPUT = man -MAN_EXTENSION = .3 -MAN_LINKS = NO -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- -GENERATE_XML = NO -XML_OUTPUT = xml -XML_SCHEMA = -XML_DTD = -XML_PROGRAMLISTING = YES -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- -GENERATE_AUTOGEN_DEF = NO -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- -GENERATE_PERLMOD = NO -PERLMOD_LATEX = NO -PERLMOD_PRETTY = YES -PERLMOD_MAKEVAR_PREFIX = -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- -ENABLE_PREPROCESSING = YES -MACRO_EXPANSION = NO -EXPAND_ONLY_PREDEF = NO -SEARCH_INCLUDES = YES -INCLUDE_PATH = -INCLUDE_FILE_PATTERNS = -PREDEFINED = IEEE8021X_EAPOL CONFIG_CTRL_IFACE -EXPAND_AS_DEFINED = -SKIP_FUNCTION_MACROS = YES -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- -TAGFILES = -GENERATE_TAGFILE = -ALLEXTERNALS = NO -EXTERNAL_GROUPS = YES -PERL_PATH = /usr/bin/perl -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- -CLASS_DIAGRAMS = NO -HIDE_UNDOC_RELATIONS = YES -HAVE_DOT = YES -CLASS_GRAPH = YES -COLLABORATION_GRAPH = YES -GROUP_GRAPHS = YES -UML_LOOK = NO -TEMPLATE_RELATIONS = NO -INCLUDE_GRAPH = YES -INCLUDED_BY_GRAPH = YES -CALL_GRAPH = YES -GRAPHICAL_HIERARCHY = YES -DIRECTORY_GRAPH = NO -DOT_IMAGE_FORMAT = png -DOT_PATH = -DOTFILE_DIRS = -MAX_DOT_GRAPH_WIDTH = 1024 -MAX_DOT_GRAPH_HEIGHT = 1024 -MAX_DOT_GRAPH_DEPTH = 1000 -DOT_TRANSPARENT = NO -DOT_MULTI_TARGETS = NO -GENERATE_LEGEND = YES -DOT_CLEANUP = YES -#--------------------------------------------------------------------------- -# Configuration::additions related to the search engine -#--------------------------------------------------------------------------- -SEARCHENGINE = YES diff --git a/contrib/wpa_supplicant/doc/driver_wrapper.doxygen b/contrib/wpa_supplicant/doc/driver_wrapper.doxygen deleted file mode 100644 index 232739a0688b..000000000000 --- a/contrib/wpa_supplicant/doc/driver_wrapper.doxygen +++ /dev/null @@ -1,180 +0,0 @@ -/** -\page driver_wrapper Driver wrapper implementation (driver.h, drivers.c) - -All hardware and driver dependent functionality is in separate C files -that implement defined wrapper functions. Other parts -of the %wpa_supplicant are designed to be hardware, driver, and operating -system independent. - -Driver wrappers need to implement whatever calls are used in the -target operating system/driver for controlling wireless LAN -devices. As an example, in case of Linux, these are mostly some glue -code and ioctl() calls and netlink message parsing for Linux Wireless -Extensions (WE). Since features required for WPA were added only recently to -Linux Wireless Extensions (in version 18), some driver specific code is used -in number of driver interface implementations. These driver dependent parts -can be replaced with generic code in driver_wext.c once the target driver -includes full support for WE-18. After that, all Linux drivers, at -least in theory, could use the same driver wrapper code. - -A driver wrapper needs to implement some or all of the functions -defined in driver.h. These functions are registered by filling struct -wpa_driver_ops with function pointers. Hardware independent parts of -%wpa_supplicant will call these functions to control the driver/wlan -card. In addition, support for driver events is required. The event -callback function, wpa_supplicant_event(), and its parameters are -documented in wpa_supplicant.h. In addition, a pointer to the 'struct -wpa_driver_ops' needs to be registered in drivers.c file. - -When porting to other operating systems, the driver wrapper should be -modified to use the native interface of the target OS. It is possible -that some extra requirements for the interface between the driver -wrapper and generic %wpa_supplicant code are discovered during porting -to a new operating system. These will be addressed on case by case -basis by modifying the interface and updating the other driver -wrappers for this. The goal is to avoid changing this interface -without very good reasons in order to limit the number of changes -needed to other wrappers and hardware independent parts of -%wpa_supplicant. When changes are required, recommended way is to -make them in backwards compatible way that allows existing driver -interface implementations to be compiled without any modification. - -Generic Linux Wireless Extensions functions are implemented in -driver_wext.c. All Linux driver wrappers can use these when the kernel -driver supports the generic ioctl()s and wireless events. Driver -specific functions are implemented in separate C files, e.g., -driver_hostap.c. These files need to define struct wpa_driver_ops -entry that will be used in wpa_supplicant.c when calling driver -functions. struct wpa_driver_ops entries are registered in drivers.c. - -In general, it is likely to be useful to first take a look at couple -of driver interface examples before starting on implementing a new -one. driver_hostap.c and driver_wext.c include a complete -implementation for Linux drivers that use %wpa_supplicant-based control -of WPA IE and roaming. driver_ndis.c (with help from driver_ndis_.c) -is an example of a complete interface for Windows NDIS interface for -drivers that generate WPA IE themselves and decide when to roam. These -example implementations include full support for all security modes. - - -\section driver_req Driver requirements for WPA - -WPA introduces new requirements for the device driver. At least some -of these need to be implemented in order to provide enough support for -%wpa_supplicant. - -\subsection driver_tkip_ccmp TKIP/CCMP - -WPA requires that the pairwise cipher suite (encryption algorithm for -unicast data packets) is TKIP or CCMP. These are new encryption -protocols and thus, the driver will need to be modified to support -them. Depending on the used wlan hardware, some parts of these may be -implemented by the hardware/firmware. - -Specification for both TKIP and CCMP is available from IEEE (IEEE -802.11i amendment). Fully functional, hardware independent -implementation of both encryption protocols is also available in Host -AP driver (driver/modules/hostap_{tkip,ccmp}.c). In addition, Linux 2.6 -kernel tree has generic implementations for WEP, TKIP, and CCMP that can -be used in Linux drivers. - -The driver will also need to provide configuration mechanism to allow -user space programs to configure TKIP and CCMP. Linux Wireless Extensions -v18 added support for configuring these algorithms and -individual/non-default keys. If the target kernel does not include WE-18, -private ioctls can be used to provide similar functionality. - -\subsection driver_roaming Roaming control and scanning support - -%wpa_supplicant can optionally control AP selection based on the -information received from Beacon and/or Probe Response frames -(ap_scan=1 mode in configuration). This means that the driver should -support external control for scan process. In case of Linux, use of -new Wireless Extensions scan support (i.e., 'iwlist wlan0 scan') is -recommended. The current driver wrapper (driver_wext.c) uses this for -scan results. - -Scan results must also include the WPA information element. Support for -this was added in WE-18. With older versions, a custom event can be used -to provide the full WPA IE (including element id and length) as a hex -string that is included in the scan results. - -%wpa_supplicant needs to also be able to request the driver to -associate with a specific BSS. Current Host AP driver and matching -driver_hostap.c wrapper uses following sequence for this -request. Similar/identical mechanism should be usable also with other -drivers. - -- set WPA IE for AssocReq with private ioctl -- set SSID with SIOCSIWESSID -- set channel/frequency with SIOCSIWFREQ -- set BSSID with SIOCSIWAP - (this last ioctl will trigger the driver to request association) - -\subsection driver_wpa_ie WPA IE generation - -%wpa_supplicant selects which cipher suites and key management suites -are used. Based on this information, it generates a WPA IE. This is -provided to the driver interface in the associate call. This does not -match with Windows NDIS drivers which generate the WPA IE -themselves. - -%wpa_supplicant allows Windows NDIS-like behavior by providing the -selected cipher and key management suites in the associate call. If -the driver generates its own WPA IE and that differs from the one -generated by %wpa_supplicant, the driver has to inform %wpa_supplicant -about the used WPA IE (i.e., the one it used in (Re)Associate -Request). This notification is done using EVENT_ASSOCINFO event (see -wpa_supplicant.h). %wpa_supplicant is normally configured to use -ap_scan=2 mode with drivers that control WPA IE generation and roaming. - -\subsection driver_events Driver events - -%wpa_supplicant needs to receive event callbacks when certain events -occur (association, disassociation, Michael MIC failure, scan results -available, PMKSA caching candidate). These events and the callback -details are defined in wpa_supplicant.h (wpa_supplicant_event() function -and enum wpa_event_type). - -On Linux, association and disassociation can use existing Wireless -Extensions event that is reporting new AP with SIOCGIWAP -event. Similarly, completion of a scan can be reported with SIOCGIWSCAN -event. - -Michael MIC failure event was added in WE-18. Older versions of Wireless -Extensions will need to use a custom event. Host AP driver used a custom -event with following contents: MLME-MICHAELMICFAILURE.indication(keyid=# -broadcast/unicast addr=addr2). This is the recommended format until -the driver can be moved to use WE-18 mechanism. - -\subsection driver_wext_summary Summary of Linux Wireless Extensions use - -AP selection depends on ap_scan configuration: - -ap_scan=1: - -- %wpa_supplicant requests scan with SIOCSIWSCAN -- driver reports scan complete with wireless event SIOCGIWSCAN -- %wpa_supplicant reads scan results with SIOCGIWSCAN (multiple call if - a larget buffer is needed) -- %wpa_supplicant decides which AP to use based on scan results -- %wpa_supplicant configures driver to associate with the selected BSS - (SIOCSIWMODE, SIOCSIWGENIE, SIOCSIWAUTH, SIOCSIWFREQ, - SIOCSIWESSID, SIOCSIWAP) - -ap_scan=2: - -- %wpa_supplicant configures driver to associate with an SSID - (SIOCSIWMODE, SIOCSIWGENIE, SIOCSIWAUTH, SIOCSIWESSID) - - -After this, both modes use similar steps: - -- optionally (or required for drivers that generate WPA/RSN IE for - (Re)AssocReq), driver reports association parameters (AssocReq IEs) - with wireless event IWEVASSOCREQIE (and optionally IWEVASSOCRESPIE) -- driver reports association with wireless event SIOCGIWAP -- %wpa_supplicant takes care of EAPOL frame handling (validating - information from associnfo and if needed, from scan results if WPA/RSN - IE from the Beacon frame is not reported through associnfo) -*/ diff --git a/contrib/wpa_supplicant/doc/eap.doxygen b/contrib/wpa_supplicant/doc/eap.doxygen deleted file mode 100644 index 988b304c62cf..000000000000 --- a/contrib/wpa_supplicant/doc/eap.doxygen +++ /dev/null @@ -1,56 +0,0 @@ -/** -\page eap_module EAP peer implementation - -Extensible Authentication Protocol (EAP) is an authentication framework -defined in RFC 3748. %wpa_supplicant uses a separate code module for EAP -peer implementation. This module was designed to use only a minimal set -of direct function calls (mainly, to debug/event functions) in order for -it to be usable in other programs. The design of the EAP -implementation is based loosely on RFC 4137. The state machine is -defined in this RFC and so is the interface between the peer state -machine and methods. As such, this RFC provides useful information for -understanding the EAP peer implementation in %wpa_supplicant. - -Some of the terminology used in EAP state machine is referring to -EAPOL (IEEE 802.1X), but there is no strict requirement on the lower -layer being IEEE 802.1X if EAP module is built for other programs than -%wpa_supplicant. These terms should be understood to refer to the -lower layer as defined in RFC 4137. - - -\section adding_eap_methods Adding EAP methods - -Each EAP method is implemented as a separate module, usually as one C -file named eap_<name of the method>.c, e.g., eap_md5.c. All EAP -methods use the same interface between the peer state machine and -method specific functions. This allows new EAP methods to be added -without modifying the core EAP state machine implementation. - -New EAP methods need to be registered by adding them into the build -(Makefile) and the EAP method registration list in the -eap_peer_register_methods() function of eap_methods.c. Each EAP -method should use a build-time configuration option, e.g., EAP_TLS, in -order to make it possible to select which of the methods are included -in the build. - -EAP methods must implement the interface defined in eap_i.h. struct -eap_method defines the needed function pointers that each EAP method -must provide. In addition, the EAP type and name are registered using -this structure. This interface is based on section 4.4 of RFC 4137. - -It is recommended that the EAP methods would use generic helper -functions, eap_msg_alloc() and eap_hdr_validate() when processing -messages. This allows code sharing and can avoid missing some of the -needed validation steps for received packets. In addition, these -functions make it easier to change between expanded and legacy EAP -header, if needed. - -When adding an EAP method that uses a vendor specific EAP type -(Expanded Type as defined in RFC 3748, Chapter 5.7), the new method -must be registered by passing vendor id instead of EAP_VENDOR_IETF to -eap_peer_method_alloc(). These methods must not try to emulate -expanded types by registering a legacy EAP method for type 254. See -eap_vendor_test.c for an example of an EAP method implementation that -is implemented as an expanded type. - -*/ diff --git a/contrib/wpa_supplicant/doc/kerneldoc2doxygen.pl b/contrib/wpa_supplicant/doc/kerneldoc2doxygen.pl deleted file mode 100755 index 68835a1ddd31..000000000000 --- a/contrib/wpa_supplicant/doc/kerneldoc2doxygen.pl +++ /dev/null @@ -1,129 +0,0 @@ -#!/usr/bin/perl -w -# -########################################################################## -# Convert kernel-doc style comments to Doxygen comments. -########################################################################## -# -# This script reads a C source file from stdin, and writes -# to stdout. Normal usage: -# -# $ mv file.c file.c.gtkdoc -# $ kerneldoc2doxygen.pl <file.c.gtkdoc >file.c -# -# Or to do the same thing with multiple files: -# $ perl -i.gtkdoc kerneldoc2doxygen.pl *.c *.h -# -# This script may also be suitable for use as a Doxygen input filter, -# but that has not been tested. -# -# Back up your source files before using this script!! -# -########################################################################## -# Copyright (C) 2003 Jonathan Foster <jon@jon-foster.co.uk> -# Copyright (C) 2005 Jouni Malinen <j@w1.fi> -# (modified for kerneldoc format used in wpa_supplicant) -# -# This program is free software; you can 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 -# or look at http://www.gnu.org/licenses/gpl.html -########################################################################## - - -########################################################################## -# -# This function converts a single comment from gtk-doc to Doxygen format. -# The parameter does not include the opening or closing lines -# (i.e. given a comment like this: -# "/**\n" -# " * FunctionName:\n" -# " * @foo: This describes the foo parameter\n" -# " * @bar: This describes the bar parameter\n" -# " * @Returns: This describes the return value\n" -# " *\n" -# " * This describes the function.\n" -# " */\n" -# This function gets: -# " * FunctionName:\n" -# " * @foo: This describes the foo parameter\n" -# " * @bar: This describes the bar parameter\n" -# " * @Returns: This describes the return value\n" -# " *\n" -# " * This describes the function.\n" -# And it returns: -# " * This describes the function.\n" -# " *\n" -# " * @param foo This describes the foo parameter\n" -# " * @param bar This describes the bar parameter\n" -# " * @return This describes the return value\n" -# ) -# -sub fixcomment { - $t = $_[0]; - - # " * func: foo" --> "\brief foo\n" - # " * struct bar: foo" --> "\brief foo\n" - # If this fails, not a kernel-doc comment ==> return unmodified. - ($t =~ s/^[\t ]*\*[\t ]*(struct )?([^ \t\n]*) - ([^\n]*)/\\brief $3\n/s) - or return $t; - - # " * Returns: foo" --> "\return foo" - $t =~ s/\n[\t ]*\*[\t ]*Returns:/\n\\return/sig; - - # " * @foo: bar" --> "\param foo bar" - # Handle two common typos: No ":", or "," instead of ":". - $t =~ s/\n[\t ]*\*[\t ]*\@([^ :,]*)[:,]?[\t ]*/\n\\param $1 /sg; - - return $t; -} - -########################################################################## -# Start of main code - -# Read entire stdin into memory - one multi-line string. -$_ = do { local $/; <> }; - -s{^/\*\n \*}{/\*\* \\file\n\\brief}; -s{ \* Copyright}{\\par Copyright\nCopyright}; - -# Fix any comments like "/*************" so they don't match. -# "/***" ===> "/* *" -s{/\*\*\*}{/\* \*}gs; - -# The main comment-detection code. -s{ - ( # $1 = Open comment - /\*\* # Open comment - (?!\*) # Do not match /*** (redundant due to fixup above). - [\t ]*\n? # If 1st line is whitespace, match the lot (including the newline). - ) - (.*?) # $2 = Body of comment (multi-line) - ( # $3 = Close comment - ( # If possible, match the whitespace before the close-comment - (?<=\n) # This part only matches after a newline - [\t ]* # Eat whitespace - )? - \*/ # Close comment - ) - } - { - $1 . fixcomment($2) . $3 - }gesx; -# ^^^^ Modes: g - Global, match all occurances. -# e - Evaluate the replacement as an expression. -# s - Single-line - allows the pattern to match across newlines. -# x - eXtended pattern, ignore embedded whitespace -# and allow comments. - -# Write results to stdout -print $_; - diff --git a/contrib/wpa_supplicant/doc/mainpage.doxygen b/contrib/wpa_supplicant/doc/mainpage.doxygen deleted file mode 100644 index 6e58af8738e0..000000000000 --- a/contrib/wpa_supplicant/doc/mainpage.doxygen +++ /dev/null @@ -1,56 +0,0 @@ -/** -\mainpage Developers' documentation for %wpa_supplicant - -%wpa_supplicant is a WPA Supplicant for Linux, BSD and Windows with -support for WPA and WPA2 (IEEE 802.11i / RSN). Supplicant is the IEEE -802.1X/WPA component that is used in the client stations. It -implements key negotiation with a WPA Authenticator and it can optionally -control roaming and IEEE 802.11 authentication/association of the wlan -driver. - -The goal of this documentation and comments in the source code is to -give enough information for other developers to understand how -%wpa_supplicant has been implemented, how it can be modified, how new -drivers can be supported, and how %wpa_supplicant can be ported to -other operating systems. If any information is missing, feel free to -contact Jouni Malinen <j@w1.fi> for more -information. Contributions as patch files are also very welcome at the -same address. Please note that %wpa_supplicant is licensed under dual -license, GPLv2 or BSD at user's choice. All contributions to -%wpa_supplicant are expected to use compatible licensing terms. - -The source code and read-only access to %wpa_supplicant CVS repository -is available from the project home page at -http://hostap.epitest.fi/wpa_supplicant/. This developers' documentation -is also available as a PDF file from -http://hostap.epitest.fi/wpa_supplicant/wpa_supplicant-devel.pdf . - -The design goal for %wpa_supplicant was to use hardware, driver, and -OS independent, portable C code for all WPA functionality. The source -code is divided into separate C files as shown on the \ref -code_structure "code structure page". All hardware/driver specific -functionality is in separate files that implement a \ref -driver_wrapper "well-defined driver API". Information about porting -to different target boards and operating systems is available on -the \ref porting "porting page". - -EAPOL (IEEE 802.1X) state machines are implemented as a separate -module that interacts with \ref eap_module "EAP peer implementation". -In addition to programs aimed at normal production use, -%wpa_supplicant source tree includes number of \ref testing_tools -"testing and development tools" that make it easier to test the -programs without having to setup a full test setup with wireless -cards. These tools can also be used to implement automatic test -suites. - -%wpa_supplicant implements a -\ref ctrl_iface_page "control interface" that can be used by -external programs to control the operations of the %wpa_supplicant -daemon and to get status information and event notifications. There is -a small C library that provides helper functions to facilitate the use of the -control interface. This library can also be used with C++. - -\image html wpa_supplicant.png "wpa_supplicant modules" -\image latex wpa_supplicant.eps "wpa_supplicant modules" width=15cm - -*/ diff --git a/contrib/wpa_supplicant/doc/porting.doxygen b/contrib/wpa_supplicant/doc/porting.doxygen deleted file mode 100644 index 581da487e20f..000000000000 --- a/contrib/wpa_supplicant/doc/porting.doxygen +++ /dev/null @@ -1,208 +0,0 @@ -/** -\page porting Porting to different target boards and operating systems - -%wpa_supplicant was designed to be easily portable to different -hardware (board, CPU) and software (OS, drivers) targets. It is -already used with number of operating systems and numerous wireless -card models and drivers. The main %wpa_supplicant repository includes -support for Linux, FreeBSD, and Windows. In addition, at least VxWorks, -PalmOS, Windows CE, and Windows Mobile are supported in separate -repositories. On the hardware -side, %wpa_supplicant is used on various systems: desktops, laptops, -PDAs, and embedded devices with CPUs including x86, PowerPC, -arm/xscale, and MIPS. Both big and little endian configurations are -supported. - - -\section ansi_c_extra Extra functions on top of ANSI C - -%wpa_supplicant is mostly using ANSI C functions that are available on -most targets. However, couple of additional functions that are common -on modern UNIX systems are used. Number of these are listed with -prototypes in common.h (the #ifdef CONFIG_ANSI_C_EXTRA block). These -functions may need to be implemented or at least defined as macros to -native functions in the target OS or C library. - -Many of the common ANSI C functions are used through a wrapper -definitions in os.h to allow these to be replaced easily with a -platform specific version in case standard C libraries are not -available. In addition, os.h defines couple of common platform -specific functions that are implemented in os_unix.c for UNIX like -targets and in os_win32.c for Win32 API. If the target platform does -not support either of these examples, a new os_*.c file may need to be -added. - -Unless OS_NO_C_LIB_DEFINES is defined, the standard ANSI C and POSIX -functions are used by defining the os_*() wrappers to use them -directly in order to avoid extra cost in size and speed. If the target -platform needs different versions of the functions, os.h can be -modified to define the suitable macros or alternatively, -OS_NO_C_LIB_DEFINES may be defined for the build and the wrapper -functions can then be implemented in a new os_*.c wrapper file. - -common.h defines number of helper macros for handling integers of -different size and byte order. Suitable version of these definitions -may need to be added for the target platform. - - -\section configuration_backend Configuration backend - -%wpa_supplicant implements a configuration interface that allows the -backend to be easily replaced in order to read configuration data from -a suitable source depending on the target platform. config.c -implements the generic code that can be shared with all configuration -backends. Each backend is implemented in its own config_*.c file. - -The included config_file.c backend uses a text file for configuration -and config_winreg.c uses Windows registry. These files can be used as -an example for a new configuration backend if the target platform uses -different mechanism for configuration parameters. In addition, -config_none.c can be used as an empty starting point for building a -new configuration backend. - - -\section driver_iface_porting Driver interface - -Unless the target OS and driver is already supported, most porting -projects have to implement a driver wrapper. This may be done by -adding a new driver interface module or modifying an existing module -(driver_*.c) if the new target is similar to one of them. \ref -driver_wrapper "Driver wrapper implementation" describes the details -of the driver interface and discusses the tasks involved in porting -this part of %wpa_supplicant. - - -\section l2_packet_porting l2_packet (link layer access) - -%wpa_supplicant needs to have access to sending and receiving layer 2 -(link layer) packets with two Ethertypes: EAP-over-LAN (EAPOL) 0x888e -and RSN pre-authentication 0x88c7. l2_packet.h defines the interfaces -used for this in the core %wpa_supplicant implementation. - -If the target operating system supports a generic mechanism for link -layer access, that is likely the best mechanism for providing the -needed functionality for %wpa_supplicant. Linux packet socket is an -example of such a generic mechanism. If this is not available, a -separate interface may need to be implemented to the network stack or -driver. This is usually an intermediate or protocol driver that is -operating between the device driver and the OS network stack. If such -a mechanism is not feasible, the interface can also be implemented -directly in the device driver. - -The main %wpa_supplicant repository includes l2_packet implementations -for Linux using packet sockets (l2_packet_linux.c), more portable -version using libpcap/libdnet libraries (l2_packet_pcap.c; this -supports WinPcap, too), and FreeBSD specific version of libpcap -interface (l2_packet_freebsd.c). - -If the target operating system is supported by libpcap (receiving) and -libdnet (sending), l2_packet_pcap.c can likely be used with minimal or -no changes. If this is not a case or a proprietary interface for link -layer is required, a new l2_packet module may need to be -added. Alternatively, struct wpa_driver_ops::send_eapol() handler can -be used to override the l2_packet library if the link layer access is -integrated with the driver interface implementation. - - -\section eloop_porting Event loop - -%wpa_supplicant uses a single process/thread model and an event loop -to provide callbacks on events (registered timeout, received packet, -signal). eloop.h defines the event loop interface. eloop.c is an -implementation of such an event loop 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 that provide similar functionality. - - -\section ctrl_iface_porting Control interface - -%wpa_supplicant uses a \ref ctrl_iface_page "control interface" -to allow external processed -to get status information and to control the operations. Currently, -this is implemented with socket based communication; both UNIX domain -sockets and UDP sockets are supported. If the target OS does not -support sockets, this interface will likely need to be modified to use -another mechanism like message queues. The control interface is -optional component, so it is also possible to run %wpa_supplicant -without porting this part. - -The %wpa_supplicant side of the control interface is implemented in -ctrl_iface.c. Matching client side is implemented as a control -interface library in wpa_ctrl.c. - - -\section entry_point Program entry point - -%wpa_supplicant defines a set of functions that can be used to -initialize main supplicant processing. Each operating system has a -mechanism for starting new processing or threads. This is usually a -function with a specific set of arguments and calling convention. This -function is responsible on initializing %wpa_supplicant. - -main.c includes an entry point for UNIX-like operating system, i.e., -main() function that uses command line arguments for setting -parameters for %wpa_supplicant. When porting to other operating -systems, similar OS-specific entry point implementation is needed. It -can be implemented in a new file that is then linked with -%wpa_supplicant instead of main.o. main.c is also a good example on -how the initialization process should be done. - -The supplicant initialization functions are defined in -wpa_supplicant_i.h. In most cases, the entry point function should -start by fetching configuration parameters. After this, a global -%wpa_supplicant context is initialized with a call to -wpa_supplicant_init(). After this, existing network interfaces can be -added with wpa_supplicant_add_iface(). wpa_supplicant_run() is then -used to start the main event loop. Once this returns at program -termination time, wpa_supplicant_deinit() is used to release global -context data. - -wpa_supplicant_add_iface() and wpa_supplicant_remove_iface() can be -used dynamically to add and remove interfaces based on when -%wpa_supplicant processing is needed for them. This can be done, e.g., -when hotplug network adapters are being inserted and ejected. It is -also possible to do this when a network interface is being -enabled/disabled if it is desirable that %wpa_supplicant processing -for the interface is fully enabled/disabled at the same time. - - -\section simple_build Simple build example - -One way to start a porting project is to begin with a very simple -build of %wpa_supplicant with WPA-PSK support and once that is -building correctly, start adding features. - -Following command can be used to build very simple version of -%wpa_supplicant: - -\verbatim -cc -o wpa_supplicant config.c eloop.c common.c md5.c rc4.c sha1.c \ - config_none.c l2_packet_none.c tls_none.c wpa.c preauth.c \ - aes_wrap.c wpa_supplicant.c events.c main_none.c drivers.c -\endverbatim - -The end result is not really very useful since it uses empty functions -for configuration parsing and layer 2 packet access and does not -include a driver interface. However, this is a good starting point -since the build is complete in the sense that all functions are -present and this is easy to configure to a build system by just -including the listed C files. - -Once this version can be build successfully, the end result can be -made functional by adding a proper program entry point (main*.c), -driver interface (driver_*.c and matching CONFIG_DRIVER_* define for -registration in drivers.c), configuration parser/writer (config_*.c), -and layer 2 packet access implementation (l2_packet_*.c). After these -components have been added, the end result should be a working -WPA/WPA2-PSK enabled supplicant. - -After the basic functionality has been verified to work, more features -can be added by linking in more files and defining C pre-processor -defines. Currently, the best source of information for what options -are available and which files needs to be included is in the Makefile -used for building the supplicant with make. Similar configuration will -be needed for build systems that either use different type of make -tool or a GUI-based project configuration. - -*/ diff --git a/contrib/wpa_supplicant/doc/testing_tools.doxygen b/contrib/wpa_supplicant/doc/testing_tools.doxygen deleted file mode 100644 index a2ae0c250fdd..000000000000 --- a/contrib/wpa_supplicant/doc/testing_tools.doxygen +++ /dev/null @@ -1,295 +0,0 @@ -/** -\page testing_tools Testing and development tools - -[ \ref eapol_test "eapol_test" | -\ref preauth_test "preauth_test" | -\ref driver_test "driver_test" | -\ref unit_tests "Unit tests" ] - -%wpa_supplicant source tree includes number of testing and development -tools that make it easier to test the programs without having to setup -a full test setup with wireless cards. In addition, these tools can be -used to implement automatic tests suites. - -\section eapol_test eapol_test - EAP peer and RADIUS client testing - -eapol_test is a program that links together the same EAP peer -implementation that %wpa_supplicant is using and the RADIUS -authentication client code from hostapd. In addition, it has minimal -glue code to combine these two components in similar ways to IEEE -802.1X/EAPOL Authenticator state machines. In other words, it -integrates IEEE 802.1X Authenticator (normally, an access point) and -IEEE 802.1X Supplicant (normally, a wireless client) together to -generate a single program that can be used to test EAP methods without -having to setup an access point and a wireless client. - -The main uses for eapol_test are in interoperability testing of EAP -methods against RADIUS servers and in development testing for new EAP -methods. It can be easily used to automate EAP testing for -interoperability and regression since the program can be run from -shell scripts without require additional test components apart from a -RADIUS server. For example, the automated EAP tests described in -eap_testing.txt are implemented with eapol_test. Similarly, eapol_test -could be used to implement an automated regression test suite for a -RADIUS authentication server. - -eapol_test uses the same build time configuration file, .config, as -%wpa_supplicant. This file is used to select which EAP methods are -included in eapol_test. This program is not built with the default -Makefile target, so a separate make command needs to be used to -compile the tool: - -\verbatim -make eapol_test -\endverbatim - -The resulting eapol_test binary has following command like options: - -\verbatim -usage: -eapol_test [-nWS] -c<conf> [-a<AS IP>] [-p<AS port>] [-s<AS secret>] \ - [-r<count>] [-t<timeout>] [-C<Connect-Info>] \ - [-M<client MAC address>] -eapol_test scard -eapol_test sim <PIN> <num triplets> [debug] - -options: - -c<conf> = configuration file - -a<AS IP> = IP address of the authentication server, default 127.0.0.1 - -p<AS port> = UDP port of the authentication server, default 1812 - -s<AS secret> = shared secret with the authentication server, default 'radius' - -r<count> = number of re-authentications - -W = wait for a control interface monitor before starting - -S = save configuration after authentiation - -n = no MPPE keys expected - -t<timeout> = sets timeout in seconds (default: 30 s) - -C<Connect-Info> = RADIUS Connect-Info (default: CONNECT 11Mbps 802.11b) - -M<client MAC address> = Set own MAC address (Calling-Station-Id, - default: 02:00:00:00:00:01) -\endverbatim - - -As an example, -\verbatim -eapol_test -ctest.conf -a127.0.0.1 -p1812 -ssecret -r1 -\endverbatim -tries to complete EAP authentication based on the network -configuration from test.conf against the RADIUS server running on the -local host. A re-authentication is triggered to test fast -re-authentication. The configuration file uses the same format for -network blocks as %wpa_supplicant. - - -\section preauth_test preauth_test - WPA2 pre-authentication and EAP peer testing - -preauth_test is similar to eapol_test in the sense that in combines -EAP peer implementation with something else, in this case, with WPA2 -pre-authentication. This tool can be used to test pre-authentication -based on the code that %wpa_supplicant is using. As such, it tests -both the %wpa_supplicant implementation and the functionality of an -access point. - -preauth_test is built with: - -\verbatim -make preauth_test -\endverbatim - -and it uses following command line arguments: - -\verbatim -usage: preauth_test <conf> <target MAC address> <ifname> -\endverbatim - -For example, -\verbatim -preauth_test test.conf 02:11:22:33:44:55 eth0 -\endverbatim -would use network configuration from test.conf to try to complete -pre-authentication with AP using BSSID 02:11:22:33:44:55. The -pre-authentication packets would be sent using the eth0 interface. - - -\section driver_test driver_test - driver interface for testing wpa_supplicant - -%wpa_supplicant was designed to support number of different ways to -communicate with a network device driver. This design uses \ref -driver_wrapper "driver interface API" and number of driver interface -implementations. One of these is driver_test.c, i.e., a test driver -interface that is actually not using any drivers. Instead, it provides -a mechanism for running %wpa_supplicant without having to have a -device driver or wireless LAN hardware for that matter. - -driver_test can be used to talk directly with hostapd's driver_test -component to create a test setup where one or more clients and access -points can be tested within one test host and without having to have -multiple wireless cards. This makes it easier to test the core code in -%wpa_supplicant, and hostapd for that matter. Since driver_test uses -the same driver API than any other driver interface implementation, -the core code of %wpa_supplicant and hostapd can be tested with the -same coverage as one would get when using real wireless cards. The -only area that is not tested is the driver interface implementation -(driver_*.c). - -Having the possibility to use simulated network components makes it -much easier to do development testing while adding new features and to -reproduce reported bugs. As such, it is often easiest to just do most -of the development and bug fixing without using real hardware. Once -the driver_test setup has been used to implement a new feature or fix -a bug, the end result can be verified with wireless LAN cards. In many -cases, this may even be unnecessary, depending on what area the -feature/bug is relating to. Of course, changes to driver interfaces -will still require use of real hardware. - -Since multiple components can be run within a single host, testing of -complex network configuration, e.g., large number of clients -association with an access point, becomes quite easy. All the tests -can also be automated without having to resort to complex test setup -using remote access to multiple computers. - -driver_test can be included in the %wpa_supplicant build in the same -way as any other driver interface, i.e., by adding the following line -into .config: - -\verbatim -CONFIG_DRIVER_TEST=y -\endverbatim - -When running %wpa_supplicant, the test interface is selected by using -\a -Dtest command line argument. The interface name (\a -i argument) -can be selected arbitrarily, i.e., it does not need to match with any -existing network interface. The interface name is used to generate a -MAC address, so when using multiple clients, each should use a -different interface, e.g., \a sta1, \a sta2, and so on. - -%wpa_supplicant and hostapd are configured in the same way as they -would be for normal use. Following example shows a simple test setup -for WPA-PSK. - -hostapd is configured with following psk-test.conf configuration file: - -\verbatim -driver=test - -interface=ap1 -logger_stdout=-1 -logger_stdout_level=0 -debug=2 -dump_file=/tmp/hostapd.dump - -test_socket=/tmp/Test/ap1 - -ssid=jkm-test-psk - -wpa=1 -wpa_key_mgmt=WPA-PSK -wpa_pairwise=TKIP -wpa_passphrase=12345678 -\endverbatim - -and started with following command: - -\verbatim -hostapd psk-test.conf -\endverbatim - -%wpa_supplicant uses following configuration file: - -\verbatim -driver_param=test_socket=/tmp/Test/ap1 - -network={ - ssid="jkm-test-psk" - key_mgmt=WPA-PSK - psk="12345678" -} -\endverbatim - -%wpa_supplicant can then be started with following command: - -\verbatim -wpa_supplicant -Dtest -cpsk-test.conf -ista1 -ddK -\endverbatim - -If run without debug information, i.e., with - -\verbatim -wpa_supplicant -Dtest -cpsk-test.conf -ista1 -\endverbatim - -%wpa_supplicant completes authentication and prints following events: - -\verbatim -Trying to associate with 02:b8:a6:62:08:5a (SSID='jkm-test-psk' freq=0 MHz) -Associated with 02:b8:a6:62:08:5a -WPA: Key negotiation completed with 02:b8:a6:62:08:5a [PTK=TKIP GTK=TKIP] -CTRL-EVENT-CONNECTED - Connection to 02:b8:a6:62:08:5a completed (auth) -\endverbatim - -If test setup is using multiple clients, it is possible to run -multiple %wpa_supplicant processes. Alternatively, the support for -multiple interfaces can be used with just one process to save some -resources on single-CPU systems. For example, following command runs -two clients: - -\verbatim -./wpa_supplicant -Dtest -cpsk-test.conf -ista1 \ - -N -Dtest -cpsk-test.conf -ista2 -\endverbatim - -This shows following event log: - -\verbatim -Trying to associate with 02:b8:a6:62:08:5a (SSID='jkm-test-psk' freq=0 MHz) -Associated with 02:b8:a6:62:08:5a -WPA: Key negotiation completed with 02:b8:a6:62:08:5a [PTK=TKIP GTK=TKIP] -CTRL-EVENT-CONNECTED - Connection to 02:b8:a6:62:08:5a completed (auth) -Trying to associate with 02:b8:a6:62:08:5a (SSID='jkm-test-psk' freq=0 MHz) -Associated with 02:b8:a6:62:08:5a -WPA: Key negotiation completed with 02:b8:a6:62:08:5a [PTK=TKIP GTK=TKIP] -CTRL-EVENT-CONNECTED - Connection to 02:b8:a6:62:08:5a completed (auth) -\endverbatim - -hostapd shows this with following events: - -\verbatim -ap1: STA 02:b5:64:63:30:63 IEEE 802.11: associated -ap1: STA 02:b5:64:63:30:63 WPA: pairwise key handshake completed (WPA) -ap1: STA 02:b5:64:63:30:63 WPA: group key handshake completed (WPA) -ap1: STA 02:2a:c4:18:5b:f3 IEEE 802.11: associated -ap1: STA 02:2a:c4:18:5b:f3 WPA: pairwise key handshake completed (WPA) -ap1: STA 02:2a:c4:18:5b:f3 WPA: group key handshake completed (WPA) -\endverbatim - -By default, driver_param is simulating a driver that uses the WPA/RSN -IE generated by %wpa_supplicant. Driver-generated IE and AssocInfo -events can be tested by adding \a use_associnfo=1 to the \a driver_param -line in the configuration file. For example: - -\verbatim -driver_param=test_socket=/tmp/Test/ap1 use_associnfo=1 -\endverbatim - - -\section unit_tests Unit tests - -Number of the components (.c files) used in %wpa_supplicant define -their own unit tests for automated validation of the basic -functionality. Most of the tests for cryptographic algorithms are -using standard test vectors to validate functionality. These tests can -be useful especially when verifying port to a new CPU target. - -In most cases, these tests are implemented in the end of the same file -with functions that are normally commented out, but ca be included by -defining a pre-processor variable when building the file separately. -The details of the needed build options are included in the Makefile -(test-* targets). All automated unit tests can be run with - -\verbatim -make tests -\endverbatim - -This make target builds and runs each test and terminates with zero -exit code if all tests were completed successfully. - -*/ diff --git a/contrib/wpa_supplicant/doc/wpa_supplicant.fig b/contrib/wpa_supplicant/doc/wpa_supplicant.fig deleted file mode 100644 index 06abfb54b61b..000000000000 --- a/contrib/wpa_supplicant/doc/wpa_supplicant.fig +++ /dev/null @@ -1,247 +0,0 @@ -#FIG 3.2 -Landscape -Center -Inches -Letter -100.00 -Single --2 -1200 2 -6 1875 4050 2925 4350 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 1875 4050 2925 4050 2925 4350 1875 4350 1875 4050 -4 0 0 50 -1 0 12 0.0000 4 180 735 2025 4275 l2_packet\001 --6 -6 3450 1200 4275 1500 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 3450 1200 4275 1200 4275 1500 3450 1500 3450 1200 -4 0 0 50 -1 0 12 0.0000 4 180 585 3600 1425 wpa_cli\001 --6 -6 4725 1200 5925 1500 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 4725 1200 5925 1200 5925 1500 4725 1500 4725 1200 -4 0 0 50 -1 0 12 0.0000 4 135 1005 4800 1425 GUI frontend\001 --6 -6 6000 2700 7200 3225 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 6000 2700 7200 2700 7200 3225 6000 3225 6000 2700 -4 0 0 50 -1 0 12 0.0000 4 135 975 6075 2925 WPA/WPA2\001 -4 0 0 50 -1 0 12 0.0000 4 135 1065 6075 3150 state machine\001 --6 -6 6000 4950 7200 5475 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 6000 4950 7200 4950 7200 5475 6000 5475 6000 4950 -4 0 0 50 -1 0 12 0.0000 4 135 360 6075 5175 EAP\001 -4 0 0 50 -1 0 12 0.0000 4 135 1065 6075 5400 state machine\001 --6 -6 8700 3000 9375 3300 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8700 3000 9375 3000 9375 3300 8700 3300 8700 3000 -4 0 0 50 -1 0 12 0.0000 4 150 480 8775 3225 crypto\001 --6 -6 4350 3900 5025 4425 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 4350 3900 5025 3900 5025 4425 4350 4425 4350 3900 -4 0 0 50 -1 0 12 0.0000 4 105 420 4500 4125 event\001 -4 0 0 50 -1 0 12 0.0000 4 180 315 4500 4350 loop\001 --6 -6 4275 2550 5100 2850 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 4275 2550 5100 2550 5100 2850 4275 2850 4275 2550 -4 0 0 50 -1 0 12 0.0000 4 135 450 4425 2775 ctrl i/f\001 --6 -6 6000 3900 7200 4425 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 6000 3900 7200 3900 7200 4425 6000 4425 6000 3900 -4 0 0 50 -1 0 12 0.0000 4 135 600 6075 4125 EAPOL\001 -4 0 0 50 -1 0 12 0.0000 4 135 1065 6075 4350 state machine\001 --6 -6 1800 6000 7800 8100 -6 1800 6000 7800 7200 -6 1800 6900 2700 7200 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 1800 6900 2700 6900 2700 7200 1800 7200 1800 6900 -4 0 0 50 -1 0 12 0.0000 4 105 375 1875 7125 wext\001 --6 -6 4725 6900 5625 7200 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 4725 6900 5625 6900 5625 7200 4725 7200 4725 6900 -4 0 0 50 -1 0 12 0.0000 4 135 555 4800 7125 hermes\001 --6 -6 6675 6900 7800 7200 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 6675 6900 7800 6900 7800 7200 6675 7200 6675 6900 -4 0 0 50 -1 0 12 0.0000 4 180 930 6750 7125 ndiswrapper\001 --6 -6 5700 6900 6600 7200 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 5700 6900 6600 6900 6600 7200 5700 7200 5700 6900 -4 0 0 50 -1 0 12 0.0000 4 135 420 5775 7125 atmel\001 --6 -6 4275 6000 5100 6300 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 4275 6000 5100 6000 5100 6300 4275 6300 4275 6000 -4 0 0 50 -1 0 12 0.0000 4 135 630 4350 6225 driver i/f\001 --6 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 2775 6900 3675 6900 3675 7200 2775 7200 2775 6900 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 3750 6900 4650 6900 4650 7200 3750 7200 3750 6900 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 - 2250 6900 2250 6600 7200 6600 7200 6900 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 3225 6900 3225 6600 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 4200 6900 4200 6600 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 5175 6900 5175 6600 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 6150 6900 6150 6600 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 4650 6600 4650 6300 -4 0 0 50 -1 0 12 0.0000 4 180 510 2850 7125 hostap\001 -4 0 0 50 -1 0 12 0.0000 4 135 600 3825 7125 madwifi\001 --6 -6 3525 7800 5775 8100 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 3525 7800 5775 7800 5775 8100 3525 8100 3525 7800 -4 0 0 50 -1 0 12 0.0000 4 135 2145 3600 8025 kernel network device driver\001 --6 -2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 - 2250 7200 4200 7800 -2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 - 7200 7200 5100 7800 --6 -6 9600 3000 10275 3300 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 9600 3000 10275 3000 10275 3300 9600 3300 9600 3000 -4 0 0 50 -1 0 12 0.0000 4 135 315 9750 3225 TLS\001 --6 -6 8100 4425 10425 7350 -6 8175 4725 9225 5025 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8175 4725 9225 4725 9225 5025 8175 5025 8175 4725 -4 0 0 50 -1 0 12 0.0000 4 135 735 8250 4950 EAP-TLS\001 --6 -6 9300 4725 10350 5025 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 9300 4725 10350 4725 10350 5025 9300 5025 9300 4725 -4 0 0 50 -1 0 12 0.0000 4 135 810 9375 4950 EAP-MD5\001 --6 -6 8175 5100 9225 5400 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8175 5100 9225 5100 9225 5400 8175 5400 8175 5100 -4 0 0 50 -1 0 12 0.0000 4 135 885 8250 5325 EAP-PEAP\001 --6 -6 9300 5100 10350 5400 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 9300 5100 10350 5100 10350 5400 9300 5400 9300 5100 -4 0 0 50 -1 0 12 0.0000 4 135 840 9375 5325 EAP-TTLS\001 --6 -6 8175 5475 9225 5775 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8175 5475 9225 5475 9225 5775 8175 5775 8175 5475 -4 0 0 50 -1 0 12 0.0000 4 135 780 8250 5700 EAP-GTC\001 --6 -6 9300 5475 10350 5775 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 9300 5475 10350 5475 10350 5775 9300 5775 9300 5475 -4 0 0 50 -1 0 12 0.0000 4 135 765 9375 5700 EAP-OTP\001 --6 -6 8175 5850 9225 6150 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8175 5850 9225 5850 9225 6150 8175 6150 8175 5850 -4 0 0 50 -1 0 12 0.0000 4 135 750 8250 6075 EAP-SIM\001 --6 -6 9300 6225 10350 6525 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 9300 6225 10350 6225 10350 6525 9300 6525 9300 6225 -4 0 0 50 -1 0 12 0.0000 4 135 465 9375 6450 LEAP\001 --6 -6 8175 6225 9225 6525 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8175 6225 9225 6225 9225 6525 8175 6525 8175 6225 -4 0 0 50 -1 0 12 0.0000 4 135 765 8250 6450 EAP-PSK\001 --6 -6 9300 5850 10350 6150 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 9300 5850 10350 5850 10350 6150 9300 6150 9300 5850 -4 0 0 50 -1 0 12 0.0000 4 135 825 9375 6075 EAP-AKA\001 --6 -6 8175 6975 9675 7275 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8175 6975 9675 6975 9675 7275 8175 7275 8175 6975 -4 0 0 50 -1 0 12 0.0000 4 135 1365 8250 7200 EAP-MSCHAPv2\001 --6 -6 9300 6600 10350 6900 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 9300 6600 10350 6600 10350 6900 9300 6900 9300 6600 -4 0 0 50 -1 0 12 0.0000 4 135 870 9375 6825 EAP-FAST\001 --6 -6 8175 6600 9225 6900 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8175 6600 9225 6600 9225 6900 8175 6900 8175 6600 -4 0 0 50 -1 0 12 0.0000 4 135 795 8250 6825 EAP-PAX\001 --6 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8100 7350 10425 7350 10425 4425 8100 4425 8100 7350 -4 0 0 50 -1 0 12 0.0000 4 135 1050 8700 4650 EAP methods\001 --6 -6 2775 5025 4050 5325 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 2775 5025 4050 5025 4050 5325 2775 5325 2775 5025 -4 0 0 50 -1 0 12 0.0000 4 135 990 2925 5250 driver events\001 --6 -6 2775 3150 4050 3450 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 2775 3150 4050 3150 4050 3450 2775 3450 2775 3150 -4 0 0 50 -1 0 12 0.0000 4 180 990 2925 3375 configuration\001 --6 -2 1 1 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 - 1275 4200 1875 4200 -2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 - 4500 2550 3900 1500 -2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 - 4800 2550 5400 1500 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 2925 4200 4350 4200 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 5025 3900 6000 3000 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 5025 4200 6000 4200 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 4650 6000 4650 4425 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 6600 4425 6600 4950 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 6600 3225 6600 3900 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 7200 5250 8100 5250 -2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 9075 4425 9075 3300 -2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 7200 3000 8700 3150 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 4650 3900 4650 2850 -2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 7200 4125 8700 3300 -2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 6000 4350 5025 6000 -2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 6000 3150 4875 6000 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 1500 2100 10800 2100 10800 7500 1500 7500 1500 2100 -2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 9900 4425 9900 3300 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 1 - 4350 3900 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 4350 3900 4050 3450 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 4350 4425 4050 5025 -4 0 0 50 -1 0 12 0.0000 4 135 915 375 3975 EAPOL and\001 -4 0 0 50 -1 0 12 0.0000 4 180 630 375 4200 pre-auth\001 -4 0 0 50 -1 0 12 0.0000 4 180 810 375 4425 ethertypes\001 -4 0 0 50 -1 0 12 0.0000 4 135 1050 375 4650 from/to kernel\001 -4 0 0 50 -1 0 12 0.0000 4 135 1920 3675 1875 frontend control interface\001 -4 0 0 50 -1 2 14 0.0000 4 210 1440 1637 2371 wpa_supplicant\001 diff --git a/contrib/wpa_supplicant/driver.h b/contrib/wpa_supplicant/driver.h deleted file mode 100644 index ba5c5e6e375e..000000000000 --- a/contrib/wpa_supplicant/driver.h +++ /dev/null @@ -1,757 +0,0 @@ -/* - * WPA Supplicant - driver interface definition - * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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_H -#define DRIVER_H - -#define WPA_SUPPLICANT_DRIVER_VERSION 2 - -#include "defs.h" - -#define AUTH_ALG_OPEN_SYSTEM 0x01 -#define AUTH_ALG_SHARED_KEY 0x02 -#define AUTH_ALG_LEAP 0x04 - -#define IEEE80211_MODE_INFRA 0 -#define IEEE80211_MODE_IBSS 1 - -#define IEEE80211_CAP_ESS 0x0001 -#define IEEE80211_CAP_IBSS 0x0002 -#define IEEE80211_CAP_PRIVACY 0x0010 - -#define SSID_MAX_WPA_IE_LEN 40 -/** - * struct wpa_scan_result - Scan results - * @bssid: BSSID - * @ssid: SSID - * @ssid_len: length of the ssid - * @wpa_ie: WPA IE - * @wpa_ie_len: length of the wpa_ie - * @rsn_ie: RSN IE - * @rsn_ie_len: length of the RSN IE - * @freq: frequency of the channel in MHz (e.g., 2412 = channel 1) - * @caps: capability information field in host byte order - * @qual: signal quality - * @noise: noise level - * @level: signal level - * @maxrate: maximum supported rate - * - * 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. - */ -struct wpa_scan_result { - u8 bssid[ETH_ALEN]; - u8 ssid[32]; - size_t ssid_len; - u8 wpa_ie[SSID_MAX_WPA_IE_LEN]; - size_t wpa_ie_len; - u8 rsn_ie[SSID_MAX_WPA_IE_LEN]; - size_t rsn_ie_len; - int freq; - u16 caps; - int qual; - int noise; - int level; - int maxrate; -}; - -/** - * 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; - 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 wpa_supplicant.h). - * 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). - */ - const u8 *wpa_ie; - /** - * wpa_ie_len - length of the wpa_ie - */ - size_t wpa_ie_len; - - /* The selected pairwise/group cipher and key management - * suites. These are usually ignored if @wpa_ie is used. */ - wpa_cipher pairwise_suite; - wpa_cipher group_suite; - wpa_key_mgmt key_mgmt_suite; - - /** - * auth_alg - Allowed authentication algorithms - * Bit field of 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 { - NO_MGMT_FRAME_PROTECTION, - MGMT_FRAME_PROTECTION_OPTIONAL, - MGMT_FRAME_PROTECTION_REQUIRED - } mgmt_frame_protection; -}; - -/** - * 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 - 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 -#define WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC 0x00000002 -#define WPA_DRIVER_FLAGS_USER_SPACE_MLME 0x00000004 - unsigned int flags; -}; - - -#define WPA_CHAN_W_SCAN 0x00000001 -#define WPA_CHAN_W_ACTIVE_SCAN 0x00000002 -#define WPA_CHAN_W_IBSS 0x00000004 - -struct wpa_channel_data { - short chan; /* channel number (IEEE 802.11) */ - short freq; /* frequency in MHz */ - int flag; /* flag for user space use (WPA_CHAN_*) */ -}; - -#define WPA_RATE_ERP 0x00000001 -#define WPA_RATE_BASIC 0x00000002 -#define WPA_RATE_PREAMBLE2 0x00000004 -#define WPA_RATE_SUPPORTED 0x00000010 -#define WPA_RATE_OFDM 0x00000020 -#define WPA_RATE_CCK 0x00000040 -#define WPA_RATE_MANDATORY 0x00000100 - -struct wpa_rate_data { - int rate; /* rate in 100 kbps */ - int flags; /* WPA_RATE_ flags */ -}; - -typedef enum { - WPA_MODE_IEEE80211B, - WPA_MODE_IEEE80211G, - WPA_MODE_IEEE80211A, - NUM_WPA_MODES -} wpa_hw_mode; - -struct wpa_hw_modes { - wpa_hw_mode mode; - int num_channels; - struct wpa_channel_data *channels; - int num_rates; - struct wpa_rate_data *rates; -}; - - -struct ieee80211_rx_status { - int channel; - int ssi; -}; - - -/** - * 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_wpa - Enable/disable WPA support (OBSOLETE) - * @priv: private driver interface data - * @enabled: 1 = enable, 0 = disable - * - * Returns: 0 on success, -1 on failure - * - * Note: This function is included for backwards compatibility. This is - * called only just after init and just before deinit, so these - * functions can be used to implement same functionality and the driver - * interface need not define this function. - * - * Configure the kernel driver to enable/disable WPA support. This may - * be empty function, if WPA support is always enabled. Common - * configuration items are WPA IE (clearing it when WPA support is - * disabled), Privacy flag configuration for capability field (note: - * this the value need to set in associate handler to allow plaintext - * mode to be used) when trying to associate with, roaming mode (can - * allow wpa_supplicant to control roaming if ap_scan=1 is used; - * however, drivers can also implement roaming if desired, especially - * ap_scan=2 mode is used for this). - */ - int (*set_wpa)(void *priv, int enabled); - - /** - * set_key - Configure encryption key - * @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_DHV); - * %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; 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) - * @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, DHV: 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 tricker 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)(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); - - /** - * 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 wpa_supplicant.h 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); - - /** - * set_drop_unencrypted - Enable/disable unencrypted frame filtering - * @priv: private driver interface data - * @enabled: 1 = unencrypted Tx/Rx frames will be dropped, 0 = disabled - * - * Returns: 0 on success, -1 on failure - * - * 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 (*set_drop_unencrypted)(void *priv, int enabled); - - /** - * scan - Request the driver to initiate scan - * @priv: private driver interface data - * @ssid: specific SSID to scan for (ProbeReq) or %NULL to scan for - * all SSIDs (either active scan with broadcast SSID or passive - * scan - * @ssid_len: length of the SSID - * - * 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_results(). - */ - int (*scan)(void *priv, const u8 *ssid, size_t ssid_len); - - /** - * get_scan_results - Fetch the latest scan results - * @priv: private driver interface data - * @results: pointer to buffer for scan results - * @max_size: maximum number of entries (buffer size) - * - * Returns: Number of scan result entries used on success, -1 on - * failure - * - * If scan results include more than max_size BSSes, max_size will be - * returned and the remaining entries will not be included in the - * buffer. - */ - int (*get_scan_results)(void *priv, - struct wpa_scan_result *results, - size_t max_size); - - /** - * 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); - - /** - * set_auth_alg - Set IEEE 802.11 authentication algorithm - * @priv: private driver interface data - * @auth_alg: bit field of AUTH_ALG_* - * - * If the driver supports more than one authentication algorithm at the - * same time, it should configure all supported algorithms. If not, one - * algorithm needs to be selected arbitrarily. Open System - * authentication should be ok for most cases and it is recommended to - * be used if other options are not supported. Static WEP configuration - * may also use Shared Key authentication and LEAP requires its own - * algorithm number. For LEAP, user can make sure that only one - * algorithm is used at a time by configuring LEAP as the only - * supported EAP method. This information is also available in - * associate() params, so set_auth_alg may not be needed in case of - * most drivers. - * - * Returns: 0 on success, -1 on failure - */ - int (*set_auth_alg)(void *priv, int auth_alg); - - /** - * 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); - - /** - * flush_pmkid - Flush PMKSA cache - * @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. - * - * 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 by calling - * wpa_supplicant_rx_eapol(). 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. - */ - struct wpa_hw_modes * (*get_hw_feature_data)(void *priv, - u16 *num_modes, - u16 *flags); - - /** - * set_channel - Set channel - * @priv: Private driver interface data - * @phymode: WPA_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, wpa_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); -}; - -#endif /* DRIVER_H */ diff --git a/contrib/wpa_supplicant/driver_ndis.c b/contrib/wpa_supplicant/driver_ndis.c deleted file mode 100644 index de3430631177..000000000000 --- a/contrib/wpa_supplicant/driver_ndis.c +++ /dev/null @@ -1,2842 +0,0 @@ -/* - * WPA Supplicant - Windows/NDIS driver interface - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 <winsock2.h> -#else /* CONFIG_USE_NDISUIO */ -#include <Packet32.h> -#endif /* CONFIG_USE_NDISUIO */ -#include <ntddndis.h> - -#ifdef _WIN32_WCE -#include <winioctl.h> -#include <nuiouser.h> -#include <devload.h> -#endif /* _WIN32_WCE */ - -#include "common.h" -#include "driver.h" -#include "wpa_supplicant.h" -#include "l2_packet.h" -#include "eloop.h" -#include "wpa.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); - - -/* 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 */ - - -#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, 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, 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. - */ - bssid[0] = 0x01; - bssid[1] = 0x80; - bssid[2] = 0xc2; - bssid[3] = 0x00; - bssid[4] = 0x00; - bssid[5] = 0x03; - return 0; - } - - return ndis_get_oid(drv, OID_802_11_BSSID, 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, 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 int wpa_driver_ndis_set_wpa(void *priv, int enabled) -{ - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); - return 0; -} - - -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(void *priv, const u8 *ssid, size_t ssid_len) -{ - struct wpa_driver_ndis_data *drv = priv; - int res; - - 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 void wpa_driver_ndis_get_ies(struct wpa_scan_result *res, u8 *ie, - size_t ie_len) -{ - u8 *pos = ie; - u8 *end = ie + ie_len; - - if (ie_len < sizeof(NDIS_802_11_FIXED_IEs)) - return; - - pos += sizeof(NDIS_802_11_FIXED_IEs); - /* wpa_hexdump(MSG_MSGDUMP, "IEs", pos, end - pos); */ - while (pos + 1 < end && pos + 2 + pos[1] <= end) { - u8 ielen = 2 + pos[1]; - if (ielen > SSID_MAX_WPA_IE_LEN) { - pos += ielen; - continue; - } - if (pos[0] == GENERIC_INFO_ELEM && pos[1] >= 4 && - os_memcmp(pos + 2, "\x00\x50\xf2\x01", 4) == 0) { - os_memcpy(res->wpa_ie, pos, ielen); - res->wpa_ie_len = ielen; - } else if (pos[0] == RSN_INFO_ELEM) { - os_memcpy(res->rsn_ie, pos, ielen); - res->rsn_ie_len = ielen; - } - pos += ielen; - } -} - - -static int wpa_driver_ndis_get_scan_results(void *priv, - struct wpa_scan_result *results, - size_t max_size) -{ - struct wpa_driver_ndis_data *drv = priv; - NDIS_802_11_BSSID_LIST_EX *b; - size_t blen, count, i; - int len, j; - char *pos; - - blen = 65535; - b = os_zalloc(blen); - if (b == NULL) - return -1; - 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 -1; - } - count = b->NumberOfItems; - - if (count > max_size) - count = max_size; - - os_memset(results, 0, max_size * sizeof(struct wpa_scan_result)); - pos = (char *) &b->Bssid[0]; - for (i = 0; i < count; i++) { - NDIS_WLAN_BSSID_EX *bss = (NDIS_WLAN_BSSID_EX *) pos; - os_memcpy(results[i].bssid, bss->MacAddress, ETH_ALEN); - os_memcpy(results[i].ssid, bss->Ssid.Ssid, - bss->Ssid.SsidLength); - results[i].ssid_len = bss->Ssid.SsidLength; - if (bss->Privacy) - results[i].caps |= IEEE80211_CAP_PRIVACY; - if (bss->InfrastructureMode == Ndis802_11IBSS) - results[i].caps |= IEEE80211_CAP_IBSS; - else if (bss->InfrastructureMode == Ndis802_11Infrastructure) - results[i].caps |= IEEE80211_CAP_ESS; - results[i].level = (int) bss->Rssi; - results[i].freq = bss->Configuration.DSConfig / 1000; - for (j = 0; j < sizeof(bss->SupportedRates); j++) { - if ((bss->SupportedRates[j] & 0x7f) > - results[i].maxrate) { - results[i].maxrate = - bss->SupportedRates[j] & 0x7f; - } - } - 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(results[i].bssid), - (int) bss->IELength); - break; - } - wpa_driver_ndis_get_ies(&results[i], bss->IEs, bss->IELength); - pos += bss->Length; - if (pos > (char *) b + blen) - break; - } - - os_free(b); - return (int) count; -} - - -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", - (char *) 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(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) -{ - 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 || os_memcmp(addr, "\xff\xff\xff\xff\xff\xff", - ETH_ALEN) == 0) { - /* 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", - (char *) 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; - - 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. */ - u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - 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, 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 & AUTH_ALG_SHARED_KEY) { - if (params->auth_alg & AUTH_ALG_OPEN_SYSTEM) - auth_mode = Ndis802_11AuthModeAutoSwitch; - else - auth_mode = Ndis802_11AuthModeShared; - } else - auth_mode = Ndis802_11AuthModeOpen; - priv_mode = Ndis802_11PrivFilterAcceptAll; - } else if (params->wpa_ie[0] == RSN_INFO_ELEM) { - priv_mode = Ndis802_11PrivFilter8021xWEP; - if (params->key_mgmt_suite == KEY_MGMT_PSK) - auth_mode = Ndis802_11AuthModeWPA2PSK; - else - auth_mode = Ndis802_11AuthModeWPA2; - } 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: - 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; - }; - - 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, 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", (char *) 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; - - 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)", - (char *) &p, 8); - return ndis_set_oid(drv, OID_802_11_PMKID, (char *) &p, 8); -} - - -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", 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", - buf + ai->OffsetRequestIEs, ai->RequestIELength); - wpa_hexdump(MSG_MSGDUMP, "NDIS: Response IEs", - buf + ai->OffsetResponseIEs, ai->ResponseIELength); - - os_memset(&data, 0, sizeof(data)); - data.assoc_info.req_ies = buf + ai->OffsetRequestIEs; - data.assoc_info.req_ies_len = ai->RequestIELength; - data.assoc_info.resp_ies = 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 (os_memcmp(drv->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) - != 0) { - 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_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); -} - - -/* 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_snprintf(event.interface_status.ifname, - sizeof(event.interface_status.ifname), "%s", drv->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", 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_strncpy(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_strncpy(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 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_strncpy(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, - 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); - - 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) { - wpa_printf(MSG_DEBUG, "NDIS: Failed to set " - "OID_802_11_INFRASTRUCTURE_MODE (%d)", - (int) mode); - /* Try to continue anyway */ - - if (!drv->has_capability && drv->capa.enc == 0) { - wpa_printf(MSG_DEBUG, "NDIS: Driver did not provide " - "any wireless capabilities - assume it is " - "a wired interface"); - drv->wired = 1; - } - } - - 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); -} - - -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_wpa, - wpa_driver_ndis_set_key, - wpa_driver_ndis_init, - wpa_driver_ndis_deinit, - NULL /* set_param */, - NULL /* set_countermeasures */, - NULL /* set_drop_unencrypted */, - wpa_driver_ndis_scan, - wpa_driver_ndis_get_scan_results, - wpa_driver_ndis_deauthenticate, - wpa_driver_ndis_disassociate, - wpa_driver_ndis_associate, - NULL /* set_auth_alg */, - 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 */ -}; diff --git a/contrib/wpa_supplicant/driver_ndis.h b/contrib/wpa_supplicant/driver_ndis.h deleted file mode 100644 index cdce4bac85ab..000000000000 --- a/contrib/wpa_supplicant/driver_ndis.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * WPA Supplicant - Windows/NDIS driver interface - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 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/contrib/wpa_supplicant/driver_wired.c b/contrib/wpa_supplicant/driver_wired.c deleted file mode 100644 index f987d3d73f54..000000000000 --- a/contrib/wpa_supplicant/driver_wired.c +++ /dev/null @@ -1,278 +0,0 @@ -/* - * WPA Supplicant - wired Ethernet driver interface - * Copyright (c) 2005-2007, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 <sys/ioctl.h> -#include <net/if.h> -#ifdef __linux__ -#include <netpacket/packet.h> -#endif /* __linux__ */ -#ifdef __FreeBSD__ -#include <net/if_dl.h> -#endif /* __FreeBSD__ */ - -#include "common.h" -#include "driver.h" -#include "wpa_supplicant.h" - - -static const u8 pae_group_addr[ETH_ALEN] = -{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 }; - - -struct wpa_driver_wired_data { - void *ctx; - int pf_sock; - char ifname[IFNAMSIZ + 1]; - int membership, multi, iff_allmulti, iff_up; -}; - - -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_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_strncpy(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_strncpy(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; - - s = socket(PF_INET, SOCK_DGRAM, 0); - if (s < 0) { - perror("socket"); - return -1; - } - - os_memset(&ifr, 0, sizeof(ifr)); - os_strncpy(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__ */ -#ifdef __FreeBSD__ - { - 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 /* __FreeBSD__ */ - - 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 int wpa_driver_wired_membership(struct wpa_driver_wired_data *drv, - const u8 *addr, int add) -{ -#ifdef __linux__ - struct packet_mreq mreq; - - if (drv->pf_sock == -1) - return -1; - - os_memset(&mreq, 0, sizeof(mreq)); - mreq.mr_ifindex = if_nametoindex(drv->ifname); - mreq.mr_type = PACKET_MR_MULTICAST; - mreq.mr_alen = ETH_ALEN; - os_memcpy(mreq.mr_address, addr, ETH_ALEN); - - if (setsockopt(drv->pf_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__ */ -} - - -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_strncpy(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 (wpa_driver_wired_membership(drv, 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 && - wpa_driver_wired_membership(drv, 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 = "wpa_supplicant wired Ethernet driver", - .get_ssid = wpa_driver_wired_get_ssid, - .get_bssid = wpa_driver_wired_get_bssid, - .init = wpa_driver_wired_init, - .deinit = wpa_driver_wired_deinit, -}; diff --git a/contrib/wpa_supplicant/drivers.c b/contrib/wpa_supplicant/drivers.c deleted file mode 100644 index d7cbbbdc32b9..000000000000 --- a/contrib/wpa_supplicant/drivers.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * WPA Supplicant / driver interface list - * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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_HOSTAP -extern struct wpa_driver_ops wpa_driver_hostap_ops; /* driver_hostap.c */ -#endif /* CONFIG_DRIVER_HOSTAP */ -#ifdef CONFIG_DRIVER_PRISM54 -extern struct wpa_driver_ops wpa_driver_prism54_ops; /* driver_prism54.c */ -#endif /* CONFIG_DRIVER_PRISM54 */ -#ifdef CONFIG_DRIVER_HERMES -extern struct wpa_driver_ops wpa_driver_hermes_ops; /* driver_hermes.c */ -#endif /* CONFIG_DRIVER_HERMES */ -#ifdef CONFIG_DRIVER_MADWIFI -extern struct wpa_driver_ops wpa_driver_madwifi_ops; /* driver_madwifi.c */ -#endif /* CONFIG_DRIVER_MADWIFI */ -#ifdef CONFIG_DRIVER_ATMEL -extern struct wpa_driver_ops wpa_driver_atmel_ops; /* driver_atmel.c */ -#endif /* CONFIG_DRIVER_ATMEL */ -#ifdef CONFIG_DRIVER_NDISWRAPPER -/* driver_ndiswrapper.c */ -extern struct wpa_driver_ops wpa_driver_ndiswrapper_ops; -#endif /* CONFIG_DRIVER_NDISWRAPPER */ -#ifdef CONFIG_DRIVER_BROADCOM -extern struct wpa_driver_ops wpa_driver_broadcom_ops; /* driver_broadcom.c */ -#endif /* CONFIG_DRIVER_BROADCOM */ -#ifdef CONFIG_DRIVER_IPW -extern struct wpa_driver_ops wpa_driver_ipw_ops; /* driver_ipw.c */ -#endif /* CONFIG_DRIVER_IPW */ -#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 */ - - -struct wpa_driver_ops *wpa_supplicant_drivers[] = -{ -#ifdef CONFIG_DRIVER_WEXT - &wpa_driver_wext_ops, -#endif /* CONFIG_DRIVER_WEXT */ -#ifdef CONFIG_DRIVER_HOSTAP - &wpa_driver_hostap_ops, -#endif /* CONFIG_DRIVER_HOSTAP */ -#ifdef CONFIG_DRIVER_PRISM54 - &wpa_driver_prism54_ops, -#endif /* CONFIG_DRIVER_PRISM54 */ -#ifdef CONFIG_DRIVER_HERMES - &wpa_driver_hermes_ops, -#endif /* CONFIG_DRIVER_HERMES */ -#ifdef CONFIG_DRIVER_MADWIFI - &wpa_driver_madwifi_ops, -#endif /* CONFIG_DRIVER_MADWIFI */ -#ifdef CONFIG_DRIVER_ATMEL - &wpa_driver_atmel_ops, -#endif /* CONFIG_DRIVER_ATMEL */ -#ifdef CONFIG_DRIVER_NDISWRAPPER - &wpa_driver_ndiswrapper_ops, -#endif /* CONFIG_DRIVER_NDISWRAPPER */ -#ifdef CONFIG_DRIVER_BROADCOM - &wpa_driver_broadcom_ops, -#endif /* CONFIG_DRIVER_BROADCOM */ -#ifdef CONFIG_DRIVER_IPW - &wpa_driver_ipw_ops, -#endif /* CONFIG_DRIVER_IPW */ -#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 */ - NULL -}; diff --git a/contrib/wpa_supplicant/eap.c b/contrib/wpa_supplicant/eap.c deleted file mode 100644 index 8021e80ff120..000000000000 --- a/contrib/wpa_supplicant/eap.c +++ /dev/null @@ -1,2134 +0,0 @@ -/* - * EAP peer state machines (RFC 4137) - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "eap_i.h" -#include "config_ssid.h" -#include "tls.h" -#include "crypto.h" -#include "pcsc_funcs.h" -#include "wpa_ctrl.h" -#include "state_machine.h" - -#define STATE_MACHINE_DATA struct eap_sm -#define STATE_MACHINE_DEBUG_PREFIX "EAP" - -#define EAP_MAX_AUTH_ROUNDS 50 - - -static Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor, - EapType method); -static u8 * eap_sm_buildNak(struct eap_sm *sm, int id, size_t *len); -static void eap_sm_processIdentity(struct eap_sm *sm, const u8 *req); -static void eap_sm_processNotify(struct eap_sm *sm, const u8 *req); -static u8 * eap_sm_buildNotify(int id, size_t *len); -static void eap_sm_parseEapReq(struct eap_sm *sm, const u8 *req, size_t len); -#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 u8 * eapol_get_eapReqData(struct eap_sm *sm, size_t *len) -{ - return sm->eapol_cb->get_eapReqData(sm->eapol_ctx, len); -} - - -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; -} - - -/* - * 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)) { - 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; -} - - -/* - * 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 u8 *eapReqData; - size_t eapReqDataLen; - - SM_ENTRY(EAP, RECEIVED); - eapReqData = eapol_get_eapReqData(sm, &eapReqDataLen); - /* parse rxReq, rxSuccess, rxFailure, reqId, reqMethod */ - eap_sm_parseEapReq(sm, eapReqData, eapReqDataLen); - 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); - goto nak; - } - - /* - * 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_sm_get_eap_methods(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; - } - - 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 wpa_ssid *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: - os_free(sm->eapRespData); - sm->eapRespData = NULL; - sm->eapRespData = eap_sm_buildNak(sm, sm->reqId, &sm->eapRespDataLen); -} - - -/* - * The method processing happens here. The request from the authenticator is - * processed, and an appropriate response packet is built. - */ -SM_STATE(EAP, METHOD) -{ - u8 *eapReqData; - size_t eapReqDataLen; - 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, &eapReqDataLen); - - /* - * 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; - os_free(sm->eapRespData); - sm->eapRespData = NULL; - sm->eapRespData = sm->m->process(sm, sm->eap_method_priv, &ret, - eapReqData, eapReqDataLen, - &sm->eapRespDataLen); - 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); - os_free(sm->lastRespData); - if (sm->eapRespData) { - if (sm->workaround) - os_memcpy(sm->last_md5, sm->req_md5, 16); - sm->lastId = sm->reqId; - sm->lastRespData = os_malloc(sm->eapRespDataLen); - if (sm->lastRespData) { - os_memcpy(sm->lastRespData, sm->eapRespData, - sm->eapRespDataLen); - sm->lastRespDataLen = sm->eapRespDataLen; - } - 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 u8 *eapReqData; - size_t eapReqDataLen; - - SM_ENTRY(EAP, IDENTITY); - eapReqData = eapol_get_eapReqData(sm, &eapReqDataLen); - eap_sm_processIdentity(sm, eapReqData); - os_free(sm->eapRespData); - sm->eapRespData = NULL; - sm->eapRespData = eap_sm_buildIdentity(sm, sm->reqId, - &sm->eapRespDataLen, 0); -} - - -/* - * Handles requests for Notification method and builds a response. - */ -SM_STATE(EAP, NOTIFICATION) -{ - const u8 *eapReqData; - size_t eapReqDataLen; - - SM_ENTRY(EAP, NOTIFICATION); - eapReqData = eapol_get_eapReqData(sm, &eapReqDataLen); - eap_sm_processNotify(sm, eapReqData); - os_free(sm->eapRespData); - sm->eapRespData = NULL; - sm->eapRespData = eap_sm_buildNotify(sm->reqId, &sm->eapRespDataLen); -} - - -/* - * This state retransmits the previous response packet. - */ -SM_STATE(EAP, RETRANSMIT) -{ - SM_ENTRY(EAP, RETRANSMIT); - os_free(sm->eapRespData); - if (sm->lastRespData) { - sm->eapRespData = os_malloc(sm->lastRespDataLen); - if (sm->eapRespData) { - os_memcpy(sm->eapRespData, sm->lastRespData, - sm->lastRespDataLen); - sm->eapRespDataLen = sm->lastRespDataLen; - } - } 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"); -} - - -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 - */ -SM_STEP(EAP) -{ - int duplicate; - - 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 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: - /* - * 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); - break; - case EAP_RECEIVED: - 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; - } - - /* - * 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); - 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; - } -} - - -static Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor, - EapType method) -{ - struct wpa_ssid *config = eap_get_config(sm); - - if (!wpa_config_allowed_eap_method(config, vendor, method)) { - wpa_printf(MSG_DEBUG, "EAP: configuration does not allow: " - "vendor %u method %u", vendor, method); - return FALSE; - } - if (eap_sm_get_eap_methods(vendor, method)) - return TRUE; - wpa_printf(MSG_DEBUG, "EAP: not included in build: " - "vendor %u method %u", vendor, method); - return FALSE; -} - - -static u8 * eap_sm_build_expanded_nak(struct eap_sm *sm, int id, size_t *len, - const struct eap_method *methods, - size_t count) -{ - struct wpa_ssid *config = eap_get_config(sm); - struct eap_hdr *resp; - u8 *pos; - int found = 0; - const struct eap_method *m; - - wpa_printf(MSG_DEBUG, "EAP: Building expanded EAP-Nak"); - - /* RFC 3748 - 5.3.2: Expanded Nak */ - *len = sizeof(struct eap_hdr) + 8; - resp = os_malloc(*len + 8 * (count + 1)); - if (resp == NULL) - return NULL; - - resp->code = EAP_CODE_RESPONSE; - resp->identifier = id; - pos = (u8 *) (resp + 1); - *pos++ = EAP_TYPE_EXPANDED; - WPA_PUT_BE24(pos, EAP_VENDOR_IETF); - pos += 3; - WPA_PUT_BE32(pos, EAP_TYPE_NAK); - pos += 4; - - 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 (wpa_config_allowed_eap_method(config, m->vendor, - m->method)) { - wpa_printf(MSG_DEBUG, "EAP: allowed type: " - "vendor=%u method=%u", - m->vendor, m->method); - *pos++ = EAP_TYPE_EXPANDED; - WPA_PUT_BE24(pos, m->vendor); - pos += 3; - WPA_PUT_BE32(pos, m->method); - pos += 4; - - (*len) += 8; - found++; - } - } - if (!found) { - wpa_printf(MSG_DEBUG, "EAP: no more allowed methods"); - *pos++ = EAP_TYPE_EXPANDED; - WPA_PUT_BE24(pos, EAP_VENDOR_IETF); - pos += 3; - WPA_PUT_BE32(pos, EAP_TYPE_NONE); - pos += 4; - - (*len) += 8; - } - - resp->length = host_to_be16(*len); - - return (u8 *) resp; -} - - -static u8 * eap_sm_buildNak(struct eap_sm *sm, int id, size_t *len) -{ - struct wpa_ssid *config = eap_get_config(sm); - struct eap_hdr *resp; - u8 *pos; - 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, len, methods, count); - - /* RFC 3748 - 5.3.1: Legacy Nak */ - *len = sizeof(struct eap_hdr) + 1; - resp = os_malloc(*len + count + 1); - if (resp == NULL) - return NULL; - - resp->code = EAP_CODE_RESPONSE; - resp->identifier = id; - pos = (u8 *) (resp + 1); - *pos++ = EAP_TYPE_NAK; - - 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 (wpa_config_allowed_eap_method(config, m->vendor, - m->method)) { - if (m->vendor != EAP_VENDOR_IETF) { - if (expanded_found) - continue; - expanded_found = 1; - *pos++ = EAP_TYPE_EXPANDED; - } else - *pos++ = m->method; - (*len)++; - found++; - } - } - if (!found) { - *pos = EAP_TYPE_NONE; - (*len)++; - } - wpa_hexdump(MSG_DEBUG, "EAP: allowed methods", - ((u8 *) (resp + 1)) + 1, found); - - resp->length = host_to_be16(*len); - - return (u8 *) resp; -} - - -static void eap_sm_processIdentity(struct eap_sm *sm, const u8 *req) -{ - const struct eap_hdr *hdr = (const struct eap_hdr *) 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 wpa_ssid *ssid) -{ - int aka = 0; - char imsi[100]; - size_t imsi_len; - struct eap_method_type *m = ssid->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(ssid->identity); - ssid->identity = os_malloc(1 + imsi_len); - if (ssid->identity == NULL) { - wpa_printf(MSG_WARNING, "Failed to allocate buffer for " - "IMSI-based identity"); - return -1; - } - - ssid->identity[0] = aka ? '0' : '1'; - os_memcpy(ssid->identity + 1, imsi, imsi_len); - ssid->identity_len = 1 + imsi_len; - - return 0; -} -#endif /* PCSC_FUNCS */ - - -static int eap_sm_set_scard_pin(struct eap_sm *sm, struct wpa_ssid *ssid) -{ -#ifdef PCSC_FUNCS - if (scard_set_pin(sm->scard_ctx, ssid->pin)) { - /* - * Make sure the same PIN is not tried again in order to avoid - * blocking SIM. - */ - os_free(ssid->pin); - ssid->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 wpa_ssid *ssid) -{ -#ifdef PCSC_FUNCS - if (eap_sm_set_scard_pin(sm, ssid)) - return -1; - - return eap_sm_imsi_identity(sm, ssid); -#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_sm_init() - * @id: EAP identifier for the packet - * @len: Pointer to a variable that will be set to the length of the response - * @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. - */ -u8 * eap_sm_buildIdentity(struct eap_sm *sm, int id, size_t *len, - int encrypted) -{ - struct wpa_ssid *config = eap_get_config(sm); - struct eap_hdr *resp; - u8 *pos; - 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; - } - - *len = sizeof(struct eap_hdr) + 1 + identity_len; - resp = os_malloc(*len); - if (resp == NULL) - return NULL; - - resp->code = EAP_CODE_RESPONSE; - resp->identifier = id; - resp->length = host_to_be16(*len); - pos = (u8 *) (resp + 1); - *pos++ = EAP_TYPE_IDENTITY; - os_memcpy(pos, identity, identity_len); - - return (u8 *) resp; -} - - -static void eap_sm_processNotify(struct eap_sm *sm, const u8 *req) -{ - const struct eap_hdr *hdr = (const struct eap_hdr *) req; - const u8 *pos; - char *msg; - size_t i, msg_len; - - pos = (const u8 *) (hdr + 1); - pos++; - - msg_len = be_to_host16(hdr->length); - if (msg_len < 5) - return; - msg_len -= 5; - 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 u8 * eap_sm_buildNotify(int id, size_t *len) -{ - struct eap_hdr *resp; - u8 *pos; - - wpa_printf(MSG_DEBUG, "EAP: Generating EAP-Response Notification"); - *len = sizeof(struct eap_hdr) + 1; - resp = os_malloc(*len); - if (resp == NULL) - return NULL; - - resp->code = EAP_CODE_RESPONSE; - resp->identifier = id; - resp->length = host_to_be16(*len); - pos = (u8 *) (resp + 1); - *pos = EAP_TYPE_NOTIFICATION; - - return (u8 *) resp; -} - - -static void eap_sm_parseEapReq(struct eap_sm *sm, const u8 *req, size_t len) -{ - 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 || len < sizeof(*hdr)) - return; - - hdr = (const struct eap_hdr *) req; - plen = be_to_host16(hdr->length); - if (plen > len) { - wpa_printf(MSG_DEBUG, "EAP: Ignored truncated EAP-Packet " - "(len=%lu plen=%lu)", - (unsigned long) len, (unsigned long) plen); - return; - } - - sm->reqId = hdr->identifier; - - if (sm->workaround) { - md5_vector(1, (const u8 **) &req, &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; - } -} - - -/** - * eap_sm_init - Allocate and initialize EAP 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_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_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 = 60; - - 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; - 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_sm_deinit - Deinitialize and free an EAP state machine - * @sm: Pointer to EAP state machine allocated with eap_sm_init() - * - * This function deinitializes EAP state machine and frees all allocated - * resources. - */ -void eap_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_sm_step - Step EAP state machine - * @sm: Pointer to EAP state machine allocated with eap_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_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_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) -{ - os_free(sm->lastRespData); - sm->lastRespData = NULL; - os_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_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_sm_get_eap_methods(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 wpa_ssid *config; - char *buf; - size_t buflen; - int len; - char *field; - char *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; - } - - buflen = 100 + os_strlen(txt) + config->ssid_len; - buf = os_malloc(buflen); - if (buf == NULL) - return; - len = os_snprintf(buf, buflen, - WPA_CTRL_REQ "%s-%d:%s needed for SSID ", - field, config->id, txt); - if (len < 0 || (size_t) len >= buflen) { - os_free(buf); - return; - } - if (config->ssid && buflen > len + config->ssid_len) { - os_memcpy(buf + len, config->ssid, config->ssid_len); - len += config->ssid_len; - buf[len] = '\0'; - } - buf[buflen - 1] = '\0'; - wpa_msg(sm->msg_ctx, MSG_INFO, "%s", buf); - os_free(buf); -} -#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 */ - - -/** - * eap_sm_request_identity - Request identity from user (ctrl_iface) - * @sm: Pointer to EAP state machine allocated with eap_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_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_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_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_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_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_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 wpa_ssid *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_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 wpa_ssid *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_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_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_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 wpa_ssid. - */ -struct wpa_ssid * eap_get_config(struct eap_sm *sm) -{ - return sm->eapol_cb->get_config(sm->eapol_ctx); -} - - -/** - * eap_get_config_password - Get identity from the network configuration - * @sm: Pointer to EAP state machine allocated with eap_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 wpa_ssid *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_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 wpa_ssid *config = eap_get_config(sm); - if (config == NULL) - return NULL; - *len = config->password_len; - return config->password; -} - - -/** - * eap_get_config_new_password - Get new password from network configuration - * @sm: Pointer to EAP state machine allocated with eap_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 wpa_ssid *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_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 wpa_ssid *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_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 wpa_ssid *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_key_available - Get key availability (eapKeyAvailable variable) - * @sm: Pointer to EAP state machine allocated with eap_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_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_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_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_sm_init() - * @len: Pointer to variable that will be set to the length of the response - * 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. - */ -u8 * eap_get_eapRespData(struct eap_sm *sm, size_t *len) -{ - u8 *resp; - - if (sm == NULL || sm->eapRespData == NULL) { - *len = 0; - return NULL; - } - - resp = sm->eapRespData; - *len = sm->eapRespDataLen; - sm->eapRespData = NULL; - sm->eapRespDataLen = 0; - - return resp; -} - - -/** - * eap_sm_register_scard_ctx - Notification of smart card context - * @sm: Pointer to EAP state machine allocated with eap_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_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) - * @msglen: Length of msg - * @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 u8 *msg, size_t msglen, size_t *plen) -{ - const struct eap_hdr *hdr; - const u8 *pos; - size_t len; - - hdr = (const struct eap_hdr *) msg; - - if (msglen < 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 > msglen) { - 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_set_config_blob - Set or add a named configuration blob - * @sm: Pointer to EAP state machine allocated with eap_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) -{ - sm->eapol_cb->set_config_blob(sm->eapol_ctx, blob); -} - - -/** - * eap_get_config_blob - Get a named configuration blob - * @sm: Pointer to EAP state machine allocated with eap_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) -{ - return sm->eapol_cb->get_config_blob(sm->eapol_ctx, name); -} - - -/** - * eap_set_force_disabled - Set force_disabled flag - * @sm: Pointer to EAP state machine allocated with eap_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_msg_alloc - Allocate a buffer for an EAP message - * @vendor: Vendor-Id (0 = IETF) - * @type: EAP type - * @len: Buffer for returning message length - * @payload_len: Payload length in bytes (data after Type) - * @code: Message Code (EAP_CODE_*) - * @identifier: Identifier - * @payload: Pointer to payload pointer that will be set to point to the - * beginning of the payload or %NULL if payload pointer is not needed - * 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. - */ -struct eap_hdr * eap_msg_alloc(int vendor, EapType type, size_t *len, - size_t payload_len, u8 code, u8 identifier, - u8 **payload) -{ - struct eap_hdr *hdr; - u8 *pos; - - *len = sizeof(struct eap_hdr) + (vendor == EAP_VENDOR_IETF ? 1 : 8) + - payload_len; - hdr = os_malloc(*len); - if (hdr) { - hdr->code = code; - hdr->identifier = identifier; - hdr->length = host_to_be16(*len); - pos = (u8 *) (hdr + 1); - if (vendor == EAP_VENDOR_IETF) { - *pos++ = type; - } else { - *pos++ = EAP_TYPE_EXPANDED; - WPA_PUT_BE24(pos, vendor); - pos += 3; - WPA_PUT_BE32(pos, type); - pos += 4; - } - if (payload) - *payload = pos; - } - - return hdr; -} - - - /** - * eap_notify_pending - Notify that EAP method is ready to re-process a request - * @sm: Pointer to EAP state machine allocated with eap_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_sm_init() - */ -void eap_invalidate_cached_session(struct eap_sm *sm) -{ - if (sm) - eap_deinit_prev_method(sm, "invalidate"); -} diff --git a/contrib/wpa_supplicant/eap.h b/contrib/wpa_supplicant/eap.h deleted file mode 100644 index f1f78c2997f6..000000000000 --- a/contrib/wpa_supplicant/eap.h +++ /dev/null @@ -1,272 +0,0 @@ -/* - * EAP peer state machine functions (RFC 4137) - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "defs.h" -#include "eap_defs.h" -#include "eap_methods.h" - -struct eap_sm; -struct wpa_ssid; -struct wpa_config_blob; - -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_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_sm_init() call - */ - struct wpa_ssid * (*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_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_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_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_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. - */ - u8 * (*get_eapReqData)(void *ctx, size_t *len); - - /** - * set_config_blob - Set named configuration blob - * @ctx: eapol_ctx from eap_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_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_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); -}; - -/** - * 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; -}; - -struct eap_sm * eap_sm_init(void *eapol_ctx, struct eapol_callbacks *eapol_cb, - void *msg_ctx, struct eap_config *conf); -void eap_sm_deinit(struct eap_sm *sm); -int eap_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); -u8 * eap_sm_buildIdentity(struct eap_sm *sm, int id, size_t *len, - 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 wpa_ssid *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); -u8 * eap_get_eapRespData(struct eap_sm *sm, size_t *len); -void eap_register_scard_ctx(struct eap_sm *sm, void *ctx); -void eap_invalidate_cached_session(struct eap_sm *sm); - -#endif /* IEEE8021X_EAPOL */ - -#endif /* EAP_H */ diff --git a/contrib/wpa_supplicant/eap_aka.c b/contrib/wpa_supplicant/eap_aka.c deleted file mode 100644 index daf7722f124f..000000000000 --- a/contrib/wpa_supplicant/eap_aka.c +++ /dev/null @@ -1,934 +0,0 @@ -/* - * EAP peer method: EAP-AKA (RFC 4187) - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "crypto.h" -#include "pcsc_funcs.h" -#include "eap_sim_common.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_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[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, SUCCESS, FAILURE } state; -}; - - -static void * eap_aka_init(struct eap_sm *sm) -{ - struct eap_aka_data *data; - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - - data->state = CONTINUE; - - return data; -} - - -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); - os_free(data); - } -} - - -static int eap_aka_umts_auth(struct eap_sm *sm, struct eap_aka_data *data) -{ - wpa_printf(MSG_DEBUG, "EAP-AKA: UMTS authentication algorithm"); -#ifdef PCSC_FUNCS - return scard_umts_auth(sm->scard_ctx, data->rand, - data->autn, data->res, &data->res_len, - data->ik, data->ck, data->auts); -#else /* PCSC_FUNCS */ - /* 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; -#endif /* PCSC_FUNCS */ -} - - -#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 u8 * eap_aka_client_error(struct eap_aka_data *data, - const struct eap_hdr *req, - size_t *respDataLen, int err) -{ - struct eap_sim_msg *msg; - - data->state = FAILURE; - data->num_id_req = 0; - data->num_notification = 0; - - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier, - EAP_TYPE_AKA, 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, respDataLen, NULL, NULL, 0); -} - - -static u8 * eap_aka_authentication_reject(struct eap_aka_data *data, - const struct eap_hdr *req, - size_t *respDataLen) -{ - struct eap_sim_msg *msg; - - data->state = FAILURE; - data->num_id_req = 0; - data->num_notification = 0; - - wpa_printf(MSG_DEBUG, "Generating EAP-AKA Authentication-Reject " - "(id=%d)", req->identifier); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier, - EAP_TYPE_AKA, - EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT); - return eap_sim_msg_finish(msg, respDataLen, NULL, NULL, 0); -} - - -static u8 * eap_aka_synchronization_failure(struct eap_aka_data *data, - const struct eap_hdr *req, - size_t *respDataLen) -{ - 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)", req->identifier); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier, - EAP_TYPE_AKA, - 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, respDataLen, NULL, NULL, 0); -} - - -static u8 * eap_aka_response_identity(struct eap_sm *sm, - struct eap_aka_data *data, - const struct eap_hdr *req, - size_t *respDataLen, - 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)", - req->identifier); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier, - EAP_TYPE_AKA, 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, respDataLen, NULL, NULL, 0); -} - - -static u8 * eap_aka_response_challenge(struct eap_aka_data *data, - const struct eap_hdr *req, - size_t *respDataLen) -{ - struct eap_sim_msg *msg; - - wpa_printf(MSG_DEBUG, "Generating EAP-AKA Challenge (id=%d)", - req->identifier); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier, - EAP_TYPE_AKA, 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); - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - return eap_sim_msg_finish(msg, respDataLen, data->k_aut, (u8 *) "", 0); -} - - -static u8 * eap_aka_response_reauth(struct eap_aka_data *data, - const struct eap_hdr *req, - size_t *respDataLen, 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)", - req->identifier); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier, - EAP_TYPE_AKA, - 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; - } - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - return eap_sim_msg_finish(msg, respDataLen, data->k_aut, nonce_s, - EAP_SIM_NONCE_S_LEN); -} - - -static u8 * eap_aka_response_notification(struct eap_aka_data *data, - const struct eap_hdr *req, - size_t *respDataLen, - 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)", - req->identifier); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier, - EAP_TYPE_AKA, 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, respDataLen, k_aut, (u8 *) "", 0); -} - - -static u8 * eap_aka_process_identity(struct eap_sm *sm, - struct eap_aka_data *data, - const struct eap_hdr *req, - size_t *respDataLen, - struct eap_sim_attrs *attr) -{ - int id_error; - - 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, req, respDataLen, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - - return eap_aka_response_identity(sm, data, req, respDataLen, - attr->id_req); -} - - -static u8 * eap_aka_process_challenge(struct eap_sm *sm, - struct eap_aka_data *data, - const struct eap_hdr *req, - size_t reqDataLen, - size_t *respDataLen, - 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"); - 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, req, respDataLen, - 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, req, respDataLen); - } else if (res == -2) { - wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication " - "failed (AUTN seq# -> AUTS)"); - return eap_aka_synchronization_failure(data, req, respDataLen); - } else if (res) { - wpa_printf(MSG_WARNING, "EAP-AKA: UMTS authentication failed"); - return eap_aka_client_error(data, req, respDataLen, - EAP_AKA_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-AKA: Selected identity for MK " - "derivation", identity, identity_len); - 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_sim_verify_mac(data->k_aut, (const u8 *) req, reqDataLen, - attr->mac, (u8 *) "", 0)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message " - "used invalid AT_MAC"); - return eap_aka_client_error(data, req, respDataLen, - 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, req, respDataLen, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - eap_aka_learn_ids(data, &eattr); - os_free(decrypted); - } - - if (data->state != FAILURE) - data->state = 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, req, respDataLen); -} - - -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 eap_hdr *req, - size_t reqDataLen, - 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_sim_verify_mac(data->k_aut, (const u8 *) req, reqDataLen, - 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 u8 * eap_aka_process_notification(struct eap_sm *sm, - struct eap_aka_data *data, - const struct eap_hdr *req, - size_t reqDataLen, - size_t *respDataLen, - 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, req, respDataLen, - 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, req, respDataLen, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - - if ((attr->notification & 0x4000) == 0 && - eap_aka_process_notification_auth(data, req, reqDataLen, attr)) { - return eap_aka_client_error(data, req, respDataLen, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - - eap_sim_report_notification(sm->msg_ctx, attr->notification, 1); - if (attr->notification >= 0 && attr->notification < 32768) { - data->state = FAILURE; - } - return eap_aka_response_notification(data, req, respDataLen, - attr->notification); -} - - -static u8 * eap_aka_process_reauthentication(struct eap_sm *sm, - struct eap_aka_data *data, - const struct eap_hdr *req, - size_t reqDataLen, - size_t *respDataLen, - struct eap_sim_attrs *attr) -{ - struct eap_sim_attrs eattr; - u8 *decrypted; - - wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Reauthentication"); - - 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, req, respDataLen, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - - data->reauth = 1; - if (eap_sim_verify_mac(data->k_aut, (const u8 *) req, reqDataLen, - attr->mac, (u8 *) "", 0)) { - wpa_printf(MSG_WARNING, "EAP-AKA: Reauthentication " - "did not have valid AT_MAC"); - return eap_aka_client_error(data, req, respDataLen, - 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, req, respDataLen, - 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, req, respDataLen, - 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, req, respDataLen, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - } - - if (eattr.counter < 0 || (size_t) eattr.counter <= data->counter) { - u8 *res; - wpa_printf(MSG_INFO, "EAP-AKA: (encr) Invalid counter " - "(%d <= %d)", eattr.counter, data->counter); - data->counter_too_small = eattr.counter; - - eap_sim_derive_keys_reauth(eattr.counter, data->reauth_id, - data->reauth_id_len, eattr.nonce_s, - data->mk, NULL, NULL); - - /* 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, req, respDataLen, 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); - - 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->state != FAILURE) - data->state = 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, req, respDataLen, 0, - data->nonce_s); -} - - -static u8 * eap_aka_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - struct eap_aka_data *data = priv; - const struct eap_hdr *req; - u8 subtype, *res; - const u8 *pos; - struct eap_sim_attrs attr; - size_t len; - - wpa_hexdump(MSG_DEBUG, "EAP-AKA: EAP data", reqData, reqDataLen); - 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, EAP_TYPE_AKA, - reqData, reqDataLen, &len); - if (pos == NULL || len < 1) { - ret->ignore = TRUE; - return NULL; - } - req = (const struct eap_hdr *) reqData; - 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, reqData + len, &attr, 1, 0)) { - res = eap_aka_client_error(data, req, respDataLen, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - goto done; - } - - switch (subtype) { - case EAP_AKA_SUBTYPE_IDENTITY: - res = eap_aka_process_identity(sm, data, req, - respDataLen, &attr); - break; - case EAP_AKA_SUBTYPE_CHALLENGE: - res = eap_aka_process_challenge(sm, data, req, len, - respDataLen, &attr); - break; - case EAP_AKA_SUBTYPE_NOTIFICATION: - res = eap_aka_process_notification(sm, data, req, len, - respDataLen, &attr); - break; - case EAP_AKA_SUBTYPE_REAUTHENTICATION: - res = eap_aka_process_reauthentication(sm, data, req, len, - respDataLen, &attr); - break; - case EAP_AKA_SUBTYPE_CLIENT_ERROR: - wpa_printf(MSG_DEBUG, "EAP-AKA: subtype Client-Error"); - res = eap_aka_client_error(data, req, respDataLen, - EAP_AKA_UNABLE_TO_PROCESS_PACKET); - break; - default: - wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown subtype=%d", subtype); - res = eap_aka_client_error(data, req, respDataLen, - 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 = 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 = METHOD_MAY_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); -} - - -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; - data->state = 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; -} diff --git a/contrib/wpa_supplicant/eap_defs.h b/contrib/wpa_supplicant/eap_defs.h deleted file mode 100644 index 8ea923a8f9d0..000000000000 --- a/contrib/wpa_supplicant/eap_defs.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * EAP server/peer: Shared EAP definitions - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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; - u16 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. */ - -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 /* draft-ietf-pppext-eap-ttls-02.txt */, - 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_FAST = 43 /* draft-cam-winget-eap-fast-05.txt */, - EAP_TYPE_PAX = 46 /* RFC 4746 */, - EAP_TYPE_PSK = 47 /* RFC 4764 */, - EAP_TYPE_SAKE = 48 /* RFC 4763 */, - EAP_TYPE_EXPANDED = 254 /* RFC 3748 */, - EAP_TYPE_GPSK = 255 /* EXPERIMENTAL - type not yet allocated - * draft-ietf-emu-eap-gpsk-01.txt */ -} EapType; - - -/* SMI Network Management Private Enterprise Code for vendor specific types */ -enum { - EAP_VENDOR_IETF = 0 -}; - -#define EAP_MSK_LEN 64 -#define EAP_EMSK_LEN 64 - -#endif /* EAP_DEFS_H */ diff --git a/contrib/wpa_supplicant/eap_fast.c b/contrib/wpa_supplicant/eap_fast.c deleted file mode 100644 index d9347a986d9d..000000000000 --- a/contrib/wpa_supplicant/eap_fast.c +++ /dev/null @@ -1,2091 +0,0 @@ -/* - * EAP peer method: EAP-FAST (draft-cam-winget-eap-fast-03.txt) - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "config_ssid.h" -#include "tls.h" -#include "eap_tlv.h" -#include "sha1.h" -#include "config.h" - -/* TODO: - * - encrypt PAC-Key in the PAC file - * - test session resumption and enable it if it interoperates - * - password change (pending mschapv2 packet; replay decrypted packet) - */ - -#define EAP_FAST_VERSION 1 -#define EAP_FAST_KEY_LEN 64 -#define EAP_FAST_PAC_KEY_LEN 32 -#define EAP_FAST_SIMCK_LEN 40 -#define EAP_FAST_SKS_LEN 40 - -#define TLS_EXT_PAC_OPAQUE 35 - -static const char *pac_file_hdr = - "wpa_supplicant EAP-FAST PAC file - version 1"; - - -static void eap_fast_deinit(struct eap_sm *sm, void *priv); - - -#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 -#define PAC_TYPE_SERVER_PROTECTED_DATA 6 -#define PAC_TYPE_A_ID_INFO 7 -#define PAC_TYPE_PAC_ACKNOWLEDGEMENT 8 -#define PAC_TYPE_PAC_INFO 9 - -struct pac_tlv_hdr { - u16 type; - u16 len; -}; - - -/* draft-cam-winget-eap-fast-provisioning-01.txt: - * 3.4 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]; - u8 client_challenge[16]; -}; - - -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; -}; - - -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; - int provisioning_allowed; /* is PAC provisioning allowed */ - int provisioning; /* doing PAC provisioning (not the normal auth) */ - - 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; - - int tls_master_secret_set; - - u8 simck[EAP_FAST_SIMCK_LEN]; - int simck_idx; -}; - - -static 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); -} - - -static struct eap_fast_pac * eap_fast_get_pac(struct eap_fast_data *data, - const u8 *a_id, size_t a_id_len) -{ - struct eap_fast_pac *pac = data->pac; - - while (pac) { - if (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 int eap_fast_add_pac(struct eap_fast_data *data, - struct eap_fast_pac *entry) -{ - struct eap_fast_pac *pac, *prev; - - if (entry == NULL || entry->a_id == NULL) - return -1; - - /* Remove a possible old entry for the matching A-ID. */ - pac = data->pac; - prev = NULL; - while (pac) { - if (pac->a_id_len == entry->a_id_len && - os_memcmp(pac->a_id, entry->a_id, pac->a_id_len) == 0) { - if (prev == NULL) { - data->pac = pac->next; - } else { - prev->next = pac->next; - } - if (data->current_pac == pac) - data->current_pac = NULL; - eap_fast_free_pac(pac); - break; - } - prev = pac; - pac = pac->next; - } - - /* Allocate a new entry and add it to the list of PACs. */ - pac = os_zalloc(sizeof(*pac)); - if (pac == NULL) - return -1; - - os_memcpy(pac->pac_key, entry->pac_key, EAP_FAST_PAC_KEY_LEN); - if (entry->pac_opaque) { - pac->pac_opaque = os_malloc(entry->pac_opaque_len); - if (pac->pac_opaque == NULL) { - eap_fast_free_pac(pac); - return -1; - } - os_memcpy(pac->pac_opaque, entry->pac_opaque, - entry->pac_opaque_len); - pac->pac_opaque_len = entry->pac_opaque_len; - } - if (entry->pac_info) { - pac->pac_info = os_malloc(entry->pac_info_len); - if (pac->pac_info == NULL) { - eap_fast_free_pac(pac); - return -1; - } - os_memcpy(pac->pac_info, entry->pac_info, - entry->pac_info_len); - pac->pac_info_len = entry->pac_info_len; - } - if (entry->a_id) { - pac->a_id = os_malloc(entry->a_id_len); - if (pac->a_id == NULL) { - eap_fast_free_pac(pac); - return -1; - } - os_memcpy(pac->a_id, entry->a_id, - entry->a_id_len); - pac->a_id_len = entry->a_id_len; - } - if (entry->i_id) { - pac->i_id = os_malloc(entry->i_id_len); - if (pac->i_id == NULL) { - eap_fast_free_pac(pac); - return -1; - } - os_memcpy(pac->i_id, entry->i_id, - entry->i_id_len); - pac->i_id_len = entry->i_id_len; - } - if (entry->a_id_info) { - pac->a_id_info = os_malloc(entry->a_id_info_len); - if (pac->a_id_info == NULL) { - eap_fast_free_pac(pac); - return -1; - } - os_memcpy(pac->a_id_info, entry->a_id_info, - entry->a_id_info_len); - pac->a_id_info_len = entry->a_id_info_len; - } - pac->next = data->pac; - data->pac = pac; - return 0; -} - - -struct eap_fast_read_ctx { - FILE *f; - const char *pos; - const char *end; -}; - -static int eap_fast_read_line(struct eap_fast_read_ctx *rc, char *buf, - size_t buf_len) -{ - char *pos; - - if (rc->f) { - if (fgets(buf, 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 >= buf_len) - len = buf_len - 1; - os_memcpy(buf, rc->pos, len); - buf[len] = '\0'; - rc->pos = l_end + 1; - } - - buf[buf_len - 1] = '\0'; - pos = buf; - while (*pos != '\0') { - if (*pos == '\n' || *pos == '\r') { - *pos = '\0'; - break; - } - 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_load_pac(struct eap_sm *sm, struct eap_fast_data *data, - const char *pac_file) -{ - struct eap_fast_read_ctx rc; - struct eap_fast_pac *pac = NULL; - int count = 0; - char *buf, *pos; - const int buf_len = 2048; - int ret = 0, line = 0; - - if (pac_file == NULL) - return -1; - - os_memset(&rc, 0, sizeof(rc)); - - 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); - return 0; - } - rc.pos = (char *) blob->data; - rc.end = (char *) blob->data + blob->len; - } else { - rc.f = fopen(pac_file, "r"); - if (rc.f == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: No PAC file '%s' - " - "assume no PAC entries have been " - "provisioned", pac_file); - return 0; - } - } - - buf = os_malloc(buf_len); - if (buf == NULL) { - return -1; - } - - line++; - if (eap_fast_read_line(&rc, buf, buf_len) < 0 || - os_strcmp(pac_file_hdr, buf) != 0) { - wpa_printf(MSG_INFO, "EAP-FAST: Unrecognized header line in " - "PAC file '%s'", pac_file); - os_free(buf); - if (rc.f) - fclose(rc.f); - return -1; - } - - while (eap_fast_read_line(&rc, buf, buf_len) == 0) { - line++; - pos = os_strchr(buf, '='); - if (pos) { - *pos++ = '\0'; - } - - if (os_strcmp(buf, "START") == 0) { - if (pac) { - wpa_printf(MSG_INFO, "EAP-FAST: START line " - "without END in '%s:%d'", - pac_file, line); - ret = -1; - break; - } - pac = os_zalloc(sizeof(*pac)); - if (pac == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: No memory for " - "PAC entry"); - ret = -1; - break; - } - } else if (os_strcmp(buf, "END") == 0) { - if (pac == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: END line " - "without START in '%s:%d'", - pac_file, line); - ret = -1; - break; - } - pac->next = data->pac; - data->pac = pac; - pac = NULL; - count++; - } else if (pac && os_strcmp(buf, "PAC-Key") == 0) { - u8 *key; - size_t key_len; - key = eap_fast_parse_hex(pos, &key_len); - if (key == NULL || key_len != EAP_FAST_PAC_KEY_LEN) { - wpa_printf(MSG_INFO, "EAP-FAST: Invalid " - "PAC-Key '%s:%d'", pac_file, line); - ret = -1; - os_free(key); - break; - } - - os_memcpy(pac->pac_key, key, EAP_FAST_PAC_KEY_LEN); - os_free(key); - } else if (pac && os_strcmp(buf, "PAC-Opaque") == 0) { - os_free(pac->pac_opaque); - pac->pac_opaque = - eap_fast_parse_hex(pos, &pac->pac_opaque_len); - if (pac->pac_opaque == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: Invalid " - "PAC-Opaque '%s:%d'", - pac_file, line); - ret = -1; - break; - } - } else if (pac && os_strcmp(buf, "A-ID") == 0) { - os_free(pac->a_id); - pac->a_id = eap_fast_parse_hex(pos, &pac->a_id_len); - if (pac->a_id == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: Invalid " - "A-ID '%s:%d'", pac_file, line); - ret = -1; - break; - } - } else if (pac && os_strcmp(buf, "I-ID") == 0) { - os_free(pac->i_id); - pac->i_id = eap_fast_parse_hex(pos, &pac->i_id_len); - if (pac->i_id == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: Invalid " - "I-ID '%s:%d'", pac_file, line); - ret = -1; - break; - } - } else if (pac && os_strcmp(buf, "A-ID-Info") == 0) { - 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) { - wpa_printf(MSG_INFO, "EAP-FAST: Invalid " - "A-ID-Info '%s:%d'", - pac_file, line); - ret = -1; - break; - } - } - } - - if (pac) { - wpa_printf(MSG_INFO, "EAP-FAST: PAC block not terminated with " - "END in '%s'", pac_file); - eap_fast_free_pac(pac); - ret = -1; - } - - os_free(buf); - if (rc.f) - fclose(rc.f); - - if (ret == 0) { - wpa_printf(MSG_DEBUG, "EAP-FAST: read %d PAC entries from " - "'%s'", count, pac_file); - } - - return ret; -} - - -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; - - if (data == NULL || *buf == NULL) - 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; - } - *buf = nbuf; - *buf_len += need; - } - - ret = os_snprintf(*pos, *buf + *buf_len - *pos, "%s=", field); - if (ret < 0 || ret >= *buf + *buf_len - *pos) - return; - *pos += ret; - *pos += wpa_snprintf_hex(*pos, *buf + *buf_len - *pos, data, len); - ret = os_snprintf(*pos, *buf + *buf_len - *pos, "\n"); - if (ret < 0 || ret >= *buf + *buf_len - *pos) - return; - *pos += ret; - - if (txt) { - ret = os_snprintf(*pos, *buf + *buf_len - *pos, - "%s-txt=", field); - if (ret < 0 || ret >= *buf + *buf_len - *pos) - return; - *pos += ret; - for (i = 0; i < len; i++) { - ret = os_snprintf(*pos, *buf + *buf_len - *pos, - "%c", data[i]); - if (ret < 0 || ret >= *buf + *buf_len - *pos) - return; - *pos += ret; - } - ret = os_snprintf(*pos, *buf + *buf_len - *pos, "\n"); - if (ret < 0 || ret >= *buf + *buf_len - *pos) - return; - *pos += ret; - } -} - - -static int eap_fast_save_pac(struct eap_sm *sm, struct eap_fast_data *data, - const char *pac_file) -{ - FILE *f; - struct eap_fast_pac *pac; - int count = 0, ret; - 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 = data->pac; - while (pac) { - ret = os_snprintf(pos, buf + buf_len - pos, "START\n"); - if (ret < 0 || ret >= buf + buf_len - pos) { - os_free(buf); - 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) { - os_free(buf); - return -1; - } - pos += ret; - count++; - pac = pac->next; - } - - if (os_strncmp(pac_file, "blob://", 7) == 0) { - struct wpa_config_blob *blob; - blob = os_zalloc(sizeof(*blob)); - if (blob == NULL) { - os_free(buf); - return -1; - } - blob->data = (u8 *) buf; - blob->len = pos - buf; - buf = NULL; - blob->name = os_strdup(pac_file + 7); - if (blob->name == NULL) { - os_free(blob->data); - os_free(blob); - return -1; - } - eap_set_config_blob(sm, blob); - } else { - f = fopen(pac_file, "w"); - if (f == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: Failed to open PAC " - "file '%s' for writing", pac_file); - os_free(buf); - return -1; - } - fprintf(f, "%s", buf); - os_free(buf); - fclose(f); - } - - wpa_printf(MSG_DEBUG, "EAP-FAST: wrote %d PAC entries into '%s'", - count, pac_file); - - return 0; -} - - -static void * eap_fast_init(struct eap_sm *sm) -{ - struct eap_fast_data *data; - struct wpa_ssid *config = eap_get_config(sm); - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->fast_version = EAP_FAST_VERSION; - - if (config && config->phase1) { - if (os_strstr(config->phase1, "fast_provisioning=1")) { - data->provisioning_allowed = 1; - wpa_printf(MSG_DEBUG, "EAP-FAST: Automatic PAC " - "provisioning is allowed"); - } - } - - if (config && config->phase2) { - char *start, *pos, *buf; - struct eap_method_type *methods = NULL, *_methods; - u8 method; - size_t num_methods = 0; - start = buf = os_strdup(config->phase2); - if (buf == NULL) { - eap_fast_deinit(sm, data); - return NULL; - } - while (start && *start != '\0') { - int vendor; - pos = os_strstr(start, "auth="); - if (pos == NULL) - break; - if (start != pos && *(pos - 1) != ' ') { - start = pos + 5; - continue; - } - - start = pos + 5; - 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, "EAP-FAST: Unsupported " - "Phase2 method '%s'", start); - } else { - num_methods++; - _methods = os_realloc( - methods, - num_methods * sizeof(*methods)); - if (_methods == NULL) { - os_free(methods); - os_free(buf); - eap_fast_deinit(sm, data); - return NULL; - } - methods = _methods; - methods[num_methods - 1].vendor = vendor; - methods[num_methods - 1].method = method; - } - - start = pos; - } - os_free(buf); - data->phase2_types = methods; - data->num_phase2_types = num_methods; - } - if (data->phase2_types == NULL) { - data->phase2_types = - eap_get_phase2_types(config, &data->num_phase2_types); - } - if (data->phase2_types == NULL) { - wpa_printf(MSG_ERROR, "EAP-FAST: No Phase2 method available"); - eap_fast_deinit(sm, data); - return NULL; - } - wpa_hexdump(MSG_DEBUG, "EAP-FAST: Phase2 EAP types", - (u8 *) data->phase2_types, - data->num_phase2_types * sizeof(struct eap_method_type)); - data->phase2_type.vendor = EAP_VENDOR_IETF; - data->phase2_type.method = EAP_TYPE_NONE; - - if (eap_tls_ssl_init(sm, &data->ssl, config)) { - wpa_printf(MSG_INFO, "EAP-FAST: Failed to initialize SSL."); - 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 */ - tls_connection_enable_workaround(sm->ssl_ctx, data->ssl.conn); - - if (eap_fast_load_pac(sm, data, config->pac_file) < 0) { - eap_fast_deinit(sm, data); - return NULL; - } - - 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_tls_ssl_deinit(sm, &data->ssl); - - pac = data->pac; - prev = NULL; - while (pac) { - prev = pac; - pac = pac->next; - eap_fast_free_pac(prev); - } - os_free(data); -} - - -static int eap_fast_encrypt(struct eap_sm *sm, struct eap_fast_data *data, - int id, const u8 *plain, size_t plain_len, - u8 **out_data, size_t *out_len) -{ - int res; - u8 *pos; - struct eap_hdr *resp; - - /* TODO: add support for fragmentation, if needed. This will need to - * add TLS Message Length field, if the frame is fragmented. */ - resp = os_malloc(sizeof(struct eap_hdr) + 2 + data->ssl.tls_out_limit); - if (resp == NULL) - return 0; - - resp->code = EAP_CODE_RESPONSE; - resp->identifier = id; - - pos = (u8 *) (resp + 1); - *pos++ = EAP_TYPE_FAST; - *pos++ = data->fast_version; - - res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn, - plain, plain_len, - pos, data->ssl.tls_out_limit); - if (res < 0) { - wpa_printf(MSG_INFO, "EAP-FAST: Failed to encrypt Phase 2 " - "data"); - os_free(resp); - return 0; - } - - *out_len = sizeof(struct eap_hdr) + 2 + res; - resp->length = host_to_be16(*out_len); - *out_data = (u8 *) resp; - return 0; -} - - -static int eap_fast_phase2_nak(struct eap_fast_data *data, - struct eap_hdr *hdr, - u8 **resp, size_t *resp_len) -{ - struct eap_hdr *resp_hdr; - u8 *pos = (u8 *) (hdr + 1); - size_t i; - - /* TODO: add support for expanded Nak */ - wpa_printf(MSG_DEBUG, "EAP-FAST: Phase 2 Request: Nak type=%d", *pos); - wpa_hexdump(MSG_DEBUG, "EAP-FAST: Allowed Phase2 EAP types", - (u8 *) data->phase2_types, - data->num_phase2_types * sizeof(struct eap_method_type)); - *resp_len = sizeof(struct eap_hdr) + 1; - *resp = os_malloc(*resp_len + data->num_phase2_types); - if (*resp == NULL) - return -1; - - resp_hdr = (struct eap_hdr *) (*resp); - resp_hdr->code = EAP_CODE_RESPONSE; - resp_hdr->identifier = hdr->identifier; - pos = (u8 *) (resp_hdr + 1); - *pos++ = EAP_TYPE_NAK; - for (i = 0; i < data->num_phase2_types; i++) { - if (data->phase2_types[i].vendor == EAP_VENDOR_IETF && - data->phase2_types[i].method < 256) { - (*resp_len)++; - *pos++ = data->phase2_types[i].method; - } - } - resp_hdr->length = host_to_be16(*resp_len); - - return 0; -} - - -static int eap_fast_derive_msk(struct eap_fast_data *data) -{ - /* Derive EAP Master Session Keys (section 5.4) */ - sha1_t_prf(data->simck, EAP_FAST_SIMCK_LEN, - "Session Key Generating Function", (u8 *) "", 0, - data->key_data, EAP_FAST_KEY_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Derived key (MSK)", - data->key_data, EAP_FAST_KEY_LEN); - - sha1_t_prf(data->simck, EAP_FAST_SIMCK_LEN, - "Extended Session Key Generating Function", - (u8 *) "", 0, data->emsk, EAP_EMSK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Derived key (EMSK)", - data->emsk, EAP_EMSK_LEN); - - data->success = 1; - - return 0; -} - - -static int eap_fast_set_tls_master_secret(struct eap_sm *sm, - struct eap_fast_data *data, - const u8 *tls, size_t tls_len) -{ - struct tls_keys keys; - u8 master_secret[48], *seed; - const u8 *server_random; - size_t seed_len, server_random_len; - - if (data->tls_master_secret_set || !data->current_pac || - tls_connection_get_keys(sm->ssl_ctx, data->ssl.conn, &keys) || - keys.client_random == NULL) { - return 0; - } - - wpa_hexdump(MSG_DEBUG, "EAP-FAST: client_random", - keys.client_random, keys.client_random_len); - - /* TLS master secret is needed before TLS library has processed this - * message which includes both ServerHello and an encrypted handshake - * message, so we need to parse server_random from this message before - * passing it to TLS library. - * - * Example TLS packet header: - * (16 03 01 00 2a 02 00 00 26 03 01 <32 bytes server_random>) - * Content Type: Handshake: 0x16 - * Version: TLS 1.0 (0x0301) - * Lenghth: 42 (0x002a) - * Handshake Type: Server Hello: 0x02 - * Length: 38 (0x000026) - * Version TLS 1.0 (0x0301) - * Random: 32 bytes - */ - if (tls_len < 43 || tls[0] != 0x16 || - tls[1] != 0x03 || tls[2] != 0x01 || - tls[5] != 0x02 || tls[9] != 0x03 || tls[10] != 0x01) { - wpa_hexdump(MSG_DEBUG, "EAP-FAST: unrecognized TLS " - "ServerHello", tls, tls_len); - return -1; - } - server_random = tls + 11; - server_random_len = 32; - wpa_hexdump(MSG_DEBUG, "EAP-FAST: server_random", - server_random, server_random_len); - - seed_len = keys.client_random_len + server_random_len; - seed = os_malloc(seed_len); - if (seed == NULL) - return -1; - os_memcpy(seed, server_random, server_random_len); - os_memcpy(seed + server_random_len, - keys.client_random, keys.client_random_len); - - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: T-PRF seed", seed, seed_len); - wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: PAC-Key", - data->current_pac->pac_key, EAP_FAST_PAC_KEY_LEN); - /* master_secret = T-PRF(PAC-Key, "PAC to master secret label hash", - * server_random + client_random, 48) */ - sha1_t_prf(data->current_pac->pac_key, EAP_FAST_PAC_KEY_LEN, - "PAC to master secret label hash", - seed, seed_len, master_secret, sizeof(master_secret)); - os_free(seed); - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: TLS pre-master-secret", - master_secret, sizeof(master_secret)); - - data->tls_master_secret_set = 1; - - return tls_connection_set_master_key(sm->ssl_ctx, data->ssl.conn, - master_secret, - sizeof(master_secret)); -} - - -static u8 * eap_fast_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, - char *label, size_t len) -{ - struct tls_keys keys; - u8 *rnd = NULL, *out; - int block_size; - - block_size = tls_connection_get_keyblock_size(sm->ssl_ctx, data->conn); - if (block_size < 0) - return NULL; - - out = os_malloc(block_size + len); - if (out == NULL) - return NULL; - - if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 1, out, - block_size + len) == 0) { - os_memmove(out, out + block_size, len); - return out; - } - - if (tls_connection_get_keys(sm->ssl_ctx, data->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; -} - - -static void eap_fast_derive_key_auth(struct eap_sm *sm, - struct eap_fast_data *data) -{ - u8 *sks; - - /* draft-cam-winget-eap-fast-05.txt: - * 5.1 EAP-FAST Authentication Phase 1: Key Derivations - * Extra key material after TLS key_block: session_ket_seed[40] - */ - - sks = eap_fast_derive_key(sm, &data->ssl, "key expansion", - EAP_FAST_SKS_LEN); - if (sks == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive " - "session_key_seed"); - return; - } - - /* - * draft-cam-winget-eap-fast-05.txt, 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, &data->ssl, "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; - } - /* - * draft-cam-winget-eap-fast-05.txt, 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->current_pac) { - eap_fast_derive_key_auth(sm, data); - } else { - eap_fast_derive_key_provisioning(sm, data); - } -} - - -static int eap_fast_phase2_request(struct eap_sm *sm, - struct eap_fast_data *data, - struct eap_method_ret *ret, - struct eap_hdr *hdr, - u8 **resp, size_t *resp_len) -{ - size_t len = be_to_host16(hdr->length); - u8 *pos; - struct eap_method_ret iret; - - 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); - switch (*pos) { - case EAP_TYPE_IDENTITY: - *resp = eap_sm_buildIdentity(sm, hdr->identifier, resp_len, 1); - break; - 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-FAST: 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_fast_phase2_nak(data, hdr, resp, resp_len)) - return -1; - return 0; - } - - if (data->phase2_priv == NULL) { - data->phase2_method = eap_sm_get_eap_methods( - data->phase2_type.vendor, - data->phase2_type.method); - if (data->phase2_method) { - 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; - sm->mschapv2_full_key = 1; - data->phase2_priv = - data->phase2_method->init(sm); - sm->init_phase2 = 0; - sm->mschapv2_full_key = 0; - sm->auth_challenge = NULL; - sm->peer_challenge = NULL; - } - } - if (data->phase2_priv == NULL || data->phase2_method == NULL) { - 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)); - *resp = data->phase2_method->process(sm, data->phase2_priv, - &iret, (u8 *) hdr, len, - resp_len); - 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) - return -1; - break; - } - return 0; -} - - -static u8 * eap_fast_tlv_nak(int vendor_id, int tlv_type, size_t *len) -{ - struct eap_tlv_nak_tlv *nak; - *len = sizeof(*nak); - nak = os_malloc(*len); - if (nak == NULL) - return NULL; - 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 (u8 *) nak; -} - - -static u8 * eap_fast_tlv_result(int status, int intermediate, size_t *len) -{ - struct eap_tlv_intermediate_result_tlv *result; - *len = sizeof(*result); - result = os_malloc(*len); - if (result == NULL) - return NULL; - 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 (u8 *) result; -} - - -static u8 * eap_fast_tlv_pac_ack(size_t *len) -{ - struct eap_tlv_result_tlv *res; - struct eap_tlv_pac_ack_tlv *ack; - - *len = sizeof(*res) + sizeof(*ack); - res = os_zalloc(*len); - if (res == NULL) - return NULL; - - res->tlv_type = host_to_be16(EAP_TLV_RESULT_TLV | - EAP_TLV_TYPE_MANDATORY); - res->length = host_to_be16(sizeof(*res) - sizeof(struct eap_tlv_hdr)); - res->status = host_to_be16(EAP_TLV_RESULT_SUCCESS); - - ack = (struct eap_tlv_pac_ack_tlv *) (res + 1); - 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 (u8 *) res; -} - - -static u8 * eap_fast_tlv_eap_payload(u8 *buf, size_t *len) -{ - struct eap_tlv_hdr *tlv; - - /* Encapsulate EAP packet in EAP Payload TLV */ - tlv = os_malloc(sizeof(*tlv) + *len); - if (tlv == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to " - "allocate memory for TLV " - "encapsulation"); - os_free(buf); - return NULL; - } - tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | - EAP_TLV_EAP_PAYLOAD_TLV); - tlv->length = host_to_be16(*len); - os_memcpy(tlv + 1, buf, *len); - os_free(buf); - *len += sizeof(*tlv); - return (u8 *) tlv; -} - - -static u8 * 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, - size_t *resp_len, int final) -{ - u8 *resp; - struct eap_tlv_intermediate_result_tlv *rresult; - struct eap_tlv_crypto_binding__tlv *rbind; - u8 isk[32], imck[60], *cmk, cmac[20], *key; - size_t key_len; - int res; - - 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); - resp = eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 1, - resp_len); - return resp; - } - - wpa_printf(MSG_DEBUG, "EAP-FAST: Determining CMK[%d] for Compound MIC " - "calculation", data->simck_idx + 1); - - /* - * draft-cam-winget-eap-fast-05.txt, 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] - */ - - os_memset(isk, 0, sizeof(isk)); - if (data->phase2_method == NULL || data->phase2_priv == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Phase 2 method not " - "available"); - return NULL; - } - if (data->phase2_method->isKeyAvailable && data->phase2_method->getKey) - { - 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 NULL; - } - if (key_len > sizeof(isk)) - key_len = sizeof(isk); - os_memcpy(isk, key, key_len); - os_free(key); - } - 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); - cmk = imck + EAP_FAST_SIMCK_LEN; - wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: CMK[j]", cmk, 20); - - 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, 20, (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"); - resp = eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 1, - resp_len); - os_memcpy(_bind->compound_mac, cmac, sizeof(cmac)); - return resp; - } - - *resp_len = sizeof(*rresult) + sizeof(*rbind); - resp = os_zalloc(*resp_len); - if (resp == NULL) - return NULL; - - /* Both intermediate and final Result TLVs are identical, so ok to use - * the same structure definition for them. */ - rresult = (struct eap_tlv_intermediate_result_tlv *) resp; - rresult->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | - (final ? EAP_TLV_RESULT_TLV : - EAP_TLV_INTERMEDIATE_RESULT_TLV)); - rresult->length = host_to_be16(2); - rresult->status = host_to_be16(EAP_TLV_RESULT_SUCCESS); - - if (!data->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; - rresult->status = host_to_be16(EAP_TLV_RESULT_FAILURE); - data->phase2_success = 0; - } - - rbind = (struct eap_tlv_crypto_binding__tlv *) (rresult + 1); - 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, 20, (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)); - - if (final && data->phase2_success) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Authentication completed " - "successfully."); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; - } - - return resp; -} - - -static u8 * eap_fast_process_pac(struct eap_sm *sm, struct eap_fast_data *data, - struct eap_method_ret *ret, - u8 *pac, size_t pac_len, size_t *resp_len) -{ - struct wpa_ssid *config = eap_get_config(sm); - struct pac_tlv_hdr *hdr; - u8 *pos; - size_t left, len; - int type, pac_key_found = 0; - struct eap_fast_pac entry; - - os_memset(&entry, 0, sizeof(entry)); - 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 eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 0, - resp_len); - } - switch (type) { - 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; - } - - 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 eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 0, - resp_len); - } - - 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 eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 0, - resp_len); - } - switch (type) { - 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; - default: - wpa_printf(MSG_DEBUG, "EAP-FAST: Ignored unknown " - "PAC-Info type %d", type); - break; - } - - 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 eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 0, - resp_len); - } - - eap_fast_add_pac(data, &entry); - eap_fast_save_pac(sm, data, config->pac_file); - - if (data->provisioning) { - /* EAP-FAST 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; - 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(resp_len); -} - - -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 u8 *in_data, size_t in_len, - u8 **out_data, size_t *out_len) -{ - u8 *in_decrypted, *pos, *end; - int len_decrypted, len; - struct eap_hdr *hdr; - u8 *resp = NULL; - size_t buf_len, resp_len; - int mandatory, tlv_type; - u8 *eap_payload_tlv = NULL, *pac = NULL; - size_t eap_payload_tlv_len = 0, pac_len = 0; - int iresult = 0, result = 0; - struct eap_tlv_crypto_binding__tlv *crypto_binding = NULL; - size_t crypto_binding_len = 0; - const u8 *msg; - size_t msg_len; - int need_more_input, stop; - - wpa_printf(MSG_DEBUG, "EAP-FAST: received %lu bytes encrypted data for" - " Phase 2", (unsigned long) in_len); - - msg = eap_tls_data_reassemble(sm, &data->ssl, in_data, in_len, - &msg_len, &need_more_input); - if (msg == NULL) - return need_more_input ? 1 : -1; - - buf_len = in_len; - if (data->ssl.tls_in_total > buf_len) - buf_len = data->ssl.tls_in_total; - in_decrypted = os_malloc(buf_len); - if (in_decrypted == NULL) { - os_free(data->ssl.tls_in); - data->ssl.tls_in = NULL; - data->ssl.tls_in_len = 0; - wpa_printf(MSG_WARNING, "EAP-FAST: failed to allocate memory " - "for decryption"); - return -1; - } - - len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn, - msg, msg_len, - in_decrypted, buf_len); - os_free(data->ssl.tls_in); - data->ssl.tls_in = NULL; - data->ssl.tls_in_len = 0; - if (len_decrypted < 0) { - wpa_printf(MSG_INFO, "EAP-FAST: Failed to decrypt Phase 2 " - "data"); - os_free(in_decrypted); - return -1; - } - - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Decrypted Phase 2 TLV(s)", - in_decrypted, len_decrypted); - - if (len_decrypted < 4) { - os_free(in_decrypted); - wpa_printf(MSG_INFO, "EAP-FAST: Too short Phase 2 " - "TLV frame (len=%d)", len_decrypted); - return -1; - } - - pos = in_decrypted; - end = in_decrypted + len_decrypted; - stop = 0; - while (pos + 4 < end && !stop) { - mandatory = pos[0] & 0x80; - tlv_type = WPA_GET_BE16(pos) & 0x3fff; - pos += 2; - len = WPA_GET_BE16(pos); - pos += 2; - if (pos + len > end) { - os_free(in_decrypted); - wpa_printf(MSG_INFO, "EAP-FAST: TLV overflow"); - return 0; - } - wpa_printf(MSG_DEBUG, "EAP-FAST: received Phase 2: " - "TLV type %d length %d%s", - tlv_type, len, mandatory ? " (mandatory)" : ""); - - switch (tlv_type) { - case EAP_TLV_EAP_PAYLOAD_TLV: - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: EAP Payload TLV", - pos, len); - eap_payload_tlv = pos; - eap_payload_tlv_len = len; - break; - case EAP_TLV_RESULT_TLV: - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Result TLV", - pos, len); - if (len < 2) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Too short " - "Result TLV"); - result = EAP_TLV_RESULT_FAILURE; - break; - } - result = WPA_GET_BE16(pos); - if (result != EAP_TLV_RESULT_SUCCESS && - result != EAP_TLV_RESULT_FAILURE) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Unknown " - "Result %d", result); - result = EAP_TLV_RESULT_FAILURE; - } - wpa_printf(MSG_DEBUG, "EAP-FAST: Result: %s", - 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"); - iresult = EAP_TLV_RESULT_FAILURE; - break; - } - iresult = WPA_GET_BE16(pos); - if (iresult != EAP_TLV_RESULT_SUCCESS && - iresult != EAP_TLV_RESULT_FAILURE) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Unknown " - "Intermediate Result %d", iresult); - iresult = EAP_TLV_RESULT_FAILURE; - } - wpa_printf(MSG_DEBUG, - "EAP-FAST: Intermediate Result: %s", - 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); - crypto_binding_len = sizeof(struct eap_tlv_hdr) + len; - if (crypto_binding_len < sizeof(*crypto_binding)) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Too short " - "Crypto-Binding TLV"); - iresult = EAP_TLV_RESULT_FAILURE; - pos = end; - break; - } - crypto_binding = - (struct eap_tlv_crypto_binding__tlv *) - (pos - sizeof(struct eap_tlv_hdr)); - break; - case EAP_TLV_PAC_TLV: - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: PAC TLV", - pos, len); - pac = pos; - pac_len = len; - break; - default: - if (mandatory) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Nak unknown " - "mandatory TLV type %d", tlv_type); - resp = eap_fast_tlv_nak(0, tlv_type, - &resp_len); - stop = 1; - } else { - wpa_printf(MSG_DEBUG, "EAP-FAST: ignored " - "unknown optional TLV type %d", - tlv_type); - } - break; - } - - pos += len; - } - - if (!resp && result == EAP_TLV_RESULT_FAILURE) { - resp = eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 0, - &resp_len); - if (!resp) { - os_free(in_decrypted); - return 0; - } - } - - if (!resp && iresult == EAP_TLV_RESULT_FAILURE) { - resp = eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 1, - &resp_len); - if (!resp) { - os_free(in_decrypted); - return 0; - } - } - - if (!resp && eap_payload_tlv) { - 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); - os_free(in_decrypted); - return 0; - } - 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"); - os_free(in_decrypted); - return 0; - } - if (hdr->code == EAP_CODE_REQUEST) { - if (eap_fast_phase2_request(sm, data, ret, hdr, - &resp, &resp_len)) { - os_free(in_decrypted); - wpa_printf(MSG_INFO, "EAP-FAST: Phase2 " - "Request processing failed"); - return 0; - } - resp = eap_fast_tlv_eap_payload(resp, &resp_len); - if (resp == NULL) { - os_free(in_decrypted); - return 0; - } - } else { - wpa_printf(MSG_INFO, "EAP-FAST: Unexpected code=%d in " - "Phase 2 EAP header", hdr->code); - os_free(in_decrypted); - return 0; - } - } - - if (!resp && crypto_binding) { - int final = result == EAP_TLV_RESULT_SUCCESS; - resp = eap_fast_process_crypto_binding(sm, data, ret, - crypto_binding, - crypto_binding_len, - &resp_len, final); - if (!resp) { - os_free(in_decrypted); - return 0; - } - } - - if (!resp && pac && result != EAP_TLV_RESULT_SUCCESS) { - wpa_printf(MSG_DEBUG, "EAP-FAST: PAC TLV without Result TLV " - "acknowledging success"); - resp = eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 0, - &resp_len); - if (!resp) { - os_free(in_decrypted); - return 0; - } - } - - if (!resp && pac && result == EAP_TLV_RESULT_SUCCESS) { - resp = eap_fast_process_pac(sm, data, ret, pac, pac_len, - &resp_len); - if (!resp) { - os_free(in_decrypted); - return 0; - } - } - - os_free(in_decrypted); - - if (resp == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: No recognized TLVs - send " - "empty response packet"); - resp = os_malloc(1); - if (resp == NULL) - return 0; - resp_len = 0; - } - - wpa_hexdump(MSG_DEBUG, "EAP-FAST: Encrypting Phase 2 data", - resp, resp_len); - if (eap_fast_encrypt(sm, data, req->identifier, resp, resp_len, - out_data, out_len)) { - wpa_printf(MSG_INFO, "EAP-FAST: Failed to encrypt a Phase 2 " - "frame"); - } - os_free(resp); - - return 0; -} - - -static u8 * eap_fast_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - const struct eap_hdr *req; - size_t left; - int res; - u8 flags, *resp, id; - const u8 *pos; - struct eap_fast_data *data = priv; - - pos = eap_tls_process_init(sm, &data->ssl, EAP_TYPE_FAST, ret, - reqData, reqDataLen, &left, &flags); - if (pos == NULL) - return NULL; - req = (const struct eap_hdr *) reqData; - id = req->identifier; - - if (flags & EAP_TLS_FLAGS_START) { - const u8 *a_id; - size_t a_id_len; - struct pac_tlv_hdr *hdr; - - wpa_printf(MSG_DEBUG, "EAP-FAST: Start (server ver=%d, own " - "ver=%d)", flags & EAP_PEAP_VERSION_MASK, - data->fast_version); - if ((flags & EAP_PEAP_VERSION_MASK) < data->fast_version) - data->fast_version = flags & EAP_PEAP_VERSION_MASK; - wpa_printf(MSG_DEBUG, "EAP-FAST: Using FAST version %d", - data->fast_version); - - a_id = pos; - a_id_len = left; - if (left > sizeof(*hdr)) { - int tlen; - hdr = (struct pac_tlv_hdr *) pos; - tlen = be_to_host16(hdr->len); - if (be_to_host16(hdr->type) == PAC_TYPE_A_ID && - sizeof(*hdr) + tlen <= left) { - a_id = (u8 *) (hdr + 1); - a_id_len = tlen; - } - } - wpa_hexdump_ascii(MSG_DEBUG, "EAP-FAST: A-ID", a_id, a_id_len); - - data->current_pac = eap_fast_get_pac(data, a_id, a_id_len); - if (data->current_pac) { - wpa_printf(MSG_DEBUG, "EAP-FAST: PAC found for this " - "A-ID"); - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-FAST: A-ID-Info", - data->current_pac->a_id_info, - data->current_pac->a_id_info_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 (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 NULL; - } - - } else if (data->current_pac) { - u8 *tlv; - size_t tlv_len, olen; - struct eap_tlv_hdr *ehdr; - olen = data->current_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, - data->current_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 NULL; - } - os_free(tlv); - } else { - u8 ciphers[2]; - if (!data->provisioning_allowed) { - wpa_printf(MSG_DEBUG, "EAP-FAST: No PAC found " - "and provisioning disabled"); - return NULL; - } - wpa_printf(MSG_DEBUG, "EAP-FAST: No PAC found - " - "starting provisioning"); - ciphers[0] = TLS_CIPHER_ANON_DH_AES128_SHA; - ciphers[1] = 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 anonymous DH for TLS " - "connection"); - return NULL; - } - 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 NULL; - } - data->provisioning = 1; - } - - 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) { - res = eap_fast_decrypt(sm, data, ret, req, pos, left, - &resp, respDataLen); - if (res < 0) { - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - /* Ack possible Alert that may have caused failure in - * decryption */ - res = 1; - } - } else { - if (eap_fast_set_tls_master_secret(sm, data, pos, left) < 0) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to configure " - "TLS master secret"); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - return NULL; - } - - res = eap_tls_process_helper(sm, &data->ssl, EAP_TYPE_FAST, - data->fast_version, id, pos, left, - &resp, respDataLen); - - if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { - wpa_printf(MSG_DEBUG, - "EAP-FAST: TLS done, proceed to Phase 2"); - data->resuming = 0; - eap_fast_derive_keys(sm, data); - } - } - - if (res == 1) - return eap_tls_build_ack(&data->ssl, respDataLen, 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; -} - - -static void * eap_fast_init_for_reauth(struct eap_sm *sm, void *priv) -{ - struct eap_fast_data *data = priv; - if (eap_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->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_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/contrib/wpa_supplicant/eap_gpsk.c b/contrib/wpa_supplicant/eap_gpsk.c deleted file mode 100644 index a9af85ca8dff..000000000000 --- a/contrib/wpa_supplicant/eap_gpsk.c +++ /dev/null @@ -1,758 +0,0 @@ -/* - * EAP peer method: EAP-GPSK (draft-ietf-emu-eap-gpsk-08.txt) - * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "config_ssid.h" -#include "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 u8 * eap_gpsk_send_gpsk_2(struct eap_gpsk_data *data, u8 identifier, - const u8 *csuite_list, size_t csuite_list_len, - size_t *respDataLen); -static u8 * eap_gpsk_send_gpsk_4(struct eap_gpsk_data *data, u8 identifier, - size_t *respDataLen); - - -#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 wpa_ssid *config = eap_get_config(sm); - struct eap_gpsk_data *data; - - if (config == NULL) { - wpa_printf(MSG_INFO, "EAP-GPSK: No configuration found"); - return NULL; - } - - if (config->eappsk == NULL) { - wpa_printf(MSG_INFO, "EAP-GPSK: No key (eappsk) configured"); - return NULL; - } - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = GPSK_1; - - if (config->nai) { - data->id_peer = os_malloc(config->nai_len); - if (data->id_peer == NULL) { - eap_gpsk_deinit(sm, data); - return NULL; - } - os_memcpy(data->id_peer, config->nai, config->nai_len); - data->id_peer_len = config->nai_len; - } - - data->psk = os_malloc(config->eappsk_len); - if (data->psk == NULL) { - eap_gpsk_deinit(sm, data); - return NULL; - } - os_memcpy(data->psk, config->eappsk, config->eappsk_len); - data->psk_len = config->eappsk_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); -} - - -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; -} - - -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; -} - - -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 u8 * eap_gpsk_process_gpsk_1(struct eap_sm *sm, - struct eap_gpsk_data *data, - struct eap_method_ret *ret, - const u8 *reqData, size_t reqDataLen, - const u8 *payload, size_t payload_len, - size_t *respDataLen) -{ - size_t csuite_list_len; - const u8 *csuite_list, *pos, *end; - const struct eap_hdr *req; - u8 *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; - } - - req = (const struct eap_hdr *) reqData; - resp = eap_gpsk_send_gpsk_2(data, req->identifier, - csuite_list, csuite_list_len, - respDataLen); - if (resp == NULL) - return NULL; - - eap_gpsk_state(data, GPSK_3); - - return (u8 *) resp; -} - - -static u8 * eap_gpsk_send_gpsk_2(struct eap_gpsk_data *data, u8 identifier, - const u8 *csuite_list, size_t csuite_list_len, - size_t *respDataLen) -{ - struct eap_hdr *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, respDataLen, len, - EAP_CODE_RESPONSE, identifier, &rpos); - if (resp == NULL) - return NULL; - - *rpos++ = EAP_GPSK_OPCODE_GPSK_2; - start = rpos; - - wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Peer", - data->id_peer, data->id_peer_len); - WPA_PUT_BE16(rpos, data->id_peer_len); - rpos += 2; - if (data->id_peer) - os_memcpy(rpos, data->id_peer, data->id_peer_len); - rpos += data->id_peer_len; - - WPA_PUT_BE16(rpos, data->id_server_len); - rpos += 2; - if (data->id_server) - os_memcpy(rpos, data->id_server, data->id_server_len); - rpos += data->id_server_len; - - if (os_get_random(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); - os_free(resp); - return NULL; - } - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer", - data->rand_peer, EAP_GPSK_RAND_LEN); - os_memcpy(rpos, data->rand_peer, EAP_GPSK_RAND_LEN); - rpos += EAP_GPSK_RAND_LEN; - - os_memcpy(rpos, data->rand_server, EAP_GPSK_RAND_LEN); - rpos += EAP_GPSK_RAND_LEN; - - WPA_PUT_BE16(rpos, csuite_list_len); - rpos += 2; - os_memcpy(rpos, csuite_list, csuite_list_len); - rpos += csuite_list_len; - - csuite = (struct eap_gpsk_csuite *) rpos; - WPA_PUT_BE32(csuite->vendor, data->vendor); - WPA_PUT_BE16(csuite->specifier, data->specifier); - rpos = (u8 *) (csuite + 1); - - 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); - os_free(resp); - return NULL; - } - - /* No PD_Payload_1 */ - WPA_PUT_BE16(rpos, 0); - rpos += 2; - - if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor, - data->specifier, start, rpos - start, rpos) < - 0) { - eap_gpsk_state(data, FAILURE); - os_free(resp); - return NULL; - } - - return (u8 *) resp; -} - - -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; -} - - -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; -} - - -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; -} - - -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; -} - - -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 u8 * eap_gpsk_process_gpsk_3(struct eap_sm *sm, - struct eap_gpsk_data *data, - struct eap_method_ret *ret, - const u8 *reqData, size_t reqDataLen, - const u8 *payload, size_t payload_len, - size_t *respDataLen) -{ - u8 *resp; - const struct eap_hdr *req; - 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)); - } - - req = (const struct eap_hdr *) reqData; - resp = eap_gpsk_send_gpsk_4(data, req->identifier, respDataLen); - if (resp == NULL) - return NULL; - - eap_gpsk_state(data, SUCCESS); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; - - return (u8 *) resp; -} - - -static u8 * eap_gpsk_send_gpsk_4(struct eap_gpsk_data *data, u8 identifier, - size_t *respDataLen) -{ - struct eap_hdr *resp; - u8 *rpos, *start; - size_t len; - - wpa_printf(MSG_DEBUG, "EAP-GPSK: Sending Response/GPSK-4"); - - len = 1 + 2 + eap_gpsk_mic_len(data->vendor, data->specifier); - - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, respDataLen, len, - EAP_CODE_RESPONSE, identifier, &rpos); - if (resp == NULL) - return NULL; - - *rpos++ = EAP_GPSK_OPCODE_GPSK_4; - start = rpos; - - /* No PD_Payload_3 */ - WPA_PUT_BE16(rpos, 0); - rpos += 2; - - if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor, - data->specifier, start, rpos - start, rpos) < - 0) { - eap_gpsk_state(data, FAILURE); - os_free(resp); - return NULL; - } - - return (u8 *) resp; -} - - -static u8 * eap_gpsk_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - struct eap_gpsk_data *data = priv; - u8 *resp; - const u8 *pos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, - reqData, reqDataLen, &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, - reqDataLen, pos + 1, len - 1, - respDataLen); - break; - case EAP_GPSK_OPCODE_GPSK_3: - resp = eap_gpsk_process_gpsk_3(sm, data, ret, reqData, - reqDataLen, pos + 1, len - 1, - respDataLen); - 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/contrib/wpa_supplicant/eap_gpsk_common.c b/contrib/wpa_supplicant/eap_gpsk_common.c deleted file mode 100644 index ec97a56f0b44..000000000000 --- a/contrib/wpa_supplicant/eap_gpsk_common.c +++ /dev/null @@ -1,425 +0,0 @@ -/* - * EAP server/peer: EAP-GPSK shared routines - * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "aes_wrap.h" -#include "crypto.h" -#ifdef EAP_GPSK_SHA256 -#include "sha256.h" -#endif /* EAP_GPSK_SHA256 */ -#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); - omac1_aes_128_vector(psk, 2, addr, vlen, hash); - 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/contrib/wpa_supplicant/eap_gpsk_common.h b/contrib/wpa_supplicant/eap_gpsk_common.h deleted file mode 100644 index a30ab97ffa07..000000000000 --- a/contrib/wpa_supplicant/eap_gpsk_common.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * EAP server/peer: EAP-GPSK shared routines - * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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/contrib/wpa_supplicant/eap_gtc.c b/contrib/wpa_supplicant/eap_gtc.c deleted file mode 100644 index ed4f8f32f629..000000000000 --- a/contrib/wpa_supplicant/eap_gtc.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * EAP peer method: EAP-GTC (RFC 3748) - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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->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 u8 * eap_gtc_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - struct eap_gtc_data *data = priv; - const struct eap_hdr *req; - struct eap_hdr *resp; - const u8 *pos, *password, *identity; - u8 *rpos; - size_t password_len, identity_len, len, plen; - int otp; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GTC, - reqData, reqDataLen, &len); - if (pos == NULL) { - ret->ignore = TRUE; - return NULL; - } - req = (const struct eap_hdr *) 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, - respDataLen, 0, EAP_CODE_RESPONSE, - req->identifier, NULL); - return (u8 *) 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, respDataLen, - plen, EAP_CODE_RESPONSE, req->identifier, &rpos); - if (resp == NULL) - return NULL; - if (data->prefix) { - os_memcpy(rpos, "RESPONSE=", 9); - rpos += 9; - os_memcpy(rpos, identity, identity_len); - rpos += identity_len; - *rpos++ = '\0'; - } - os_memcpy(rpos, password, password_len); - wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-GTC: Response", - (u8 *) (resp + 1) + 1, plen); - - if (otp) { - wpa_printf(MSG_DEBUG, "EAP-GTC: Forgetting used password"); - eap_clear_config_otp(sm); - } - - return (u8 *) 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/contrib/wpa_supplicant/eap_i.h b/contrib/wpa_supplicant/eap_i.h deleted file mode 100644 index ad7a1dd496d9..000000000000 --- a/contrib/wpa_supplicant/eap_i.h +++ /dev/null @@ -1,356 +0,0 @@ -/* - * EAP peer state machines internal structures (RFC 4137) - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "eap.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_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_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_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) - * @reqDataLen: Length of the EAP request - * @respDataLen: Length of the returned EAP response - * 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. - */ - u8 * (*process)(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const u8 *reqData, size_t reqDataLen, - size_t *respDataLen); - - /** - * isKeyAvailable - Find out whether EAP method has keying material - * @sm: Pointer to EAP state machine allocated with eap_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_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_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_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_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_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_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_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; - u8 *lastRespData; - size_t lastRespDataLen; - 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 */ - u8 *eapRespData; /* peer to lower layer */ - size_t eapRespDataLen; /* 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 mschapv2_full_key; /* Request full MSCHAPv2 key */ - - int num_rounds; - int force_disabled; -}; - -const u8 * eap_hdr_validate(int vendor, EapType eap_type, - const u8 *msg, size_t msglen, size_t *plen); -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_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); -struct wpa_ssid * 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); -struct eap_hdr * eap_msg_alloc(int vendor, EapType type, size_t *len, - size_t payload_len, u8 code, u8 identifier, - u8 **payload); -void eap_notify_pending(struct eap_sm *sm); - -#endif /* EAP_I_H */ diff --git a/contrib/wpa_supplicant/eap_leap.c b/contrib/wpa_supplicant/eap_leap.c deleted file mode 100644 index aa6e05707d41..000000000000 --- a/contrib/wpa_supplicant/eap_leap.c +++ /dev/null @@ -1,399 +0,0 @@ -/* - * EAP peer method: LEAP - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "ms_funcs.h" -#include "crypto.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 u8 * eap_leap_process_request(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - struct eap_leap_data *data = priv; - const struct eap_hdr *req; - struct eap_hdr *resp; - const u8 *pos, *challenge, *identity, *password; - u8 challenge_len, *rpos; - size_t identity_len, password_len; - - wpa_printf(MSG_DEBUG, "EAP-LEAP: Processing EAP-Request"); - - identity = eap_get_config_identity(sm, &identity_len); - password = eap_get_config_password(sm, &password_len); - if (identity == NULL || password == NULL) - return NULL; - - req = (const struct eap_hdr *) reqData; - pos = (const u8 *) (req + 1); - if (reqDataLen < sizeof(*req) + 4 || *pos != EAP_TYPE_LEAP) { - wpa_printf(MSG_INFO, "EAP-LEAP: Invalid EAP-Request frame"); - ret->ignore = TRUE; - return NULL; - } - pos++; - - 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 > reqDataLen - sizeof(*req) - 4) { - wpa_printf(MSG_INFO, "EAP-LEAP: Invalid challenge " - "(challenge_len=%d reqDataLen=%lu)", - challenge_len, (unsigned long) reqDataLen); - 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, respDataLen, - 3 + LEAP_RESPONSE_LEN + identity_len, - EAP_CODE_RESPONSE, req->identifier, &rpos); - if (resp == NULL) - return NULL; - *rpos++ = LEAP_VERSION; - *rpos++ = 0; /* unused */ - *rpos++ = LEAP_RESPONSE_LEN; - 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); - rpos += LEAP_RESPONSE_LEN; - os_memcpy(rpos, identity, identity_len); - - data->state = LEAP_WAIT_SUCCESS; - - return (u8 *) resp; -} - - -static u8 * eap_leap_process_success(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const u8 *reqData, size_t *respDataLen) -{ - struct eap_leap_data *data = priv; - const struct eap_hdr *req; - struct eap_hdr *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; - } - - req = (const struct eap_hdr *) reqData; - - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_LEAP, respDataLen, - 3 + LEAP_CHALLENGE_LEN + identity_len, - EAP_CODE_REQUEST, req->identifier, &pos); - if (resp == NULL) - return NULL; - *pos++ = LEAP_VERSION; - *pos++ = 0; /* unused */ - *pos++ = LEAP_CHALLENGE_LEN; - if (hostapd_get_rand(pos, LEAP_CHALLENGE_LEN)) { - wpa_printf(MSG_WARNING, "EAP-LEAP: Failed to read random data " - "for challenge"); - os_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); - pos += LEAP_CHALLENGE_LEN; - os_memcpy(pos, identity, identity_len); - - data->state = LEAP_WAIT_RESPONSE; - - return (u8 *) resp; -} - - -static u8 * eap_leap_process_response(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const u8 *reqData, size_t reqDataLen) -{ - struct eap_leap_data *data = priv; - const struct eap_hdr *resp; - const u8 *pos, *password; - u8 response_len, pw_hash[16], pw_hash_hash[16], - expected[LEAP_RESPONSE_LEN]; - size_t password_len; - - wpa_printf(MSG_DEBUG, "EAP-LEAP: Processing EAP-Response"); - - password = eap_get_config_password(sm, &password_len); - if (password == NULL) - return NULL; - - resp = (const struct eap_hdr *) reqData; - pos = (const u8 *) (resp + 1); - if (reqDataLen < sizeof(*resp) + 4 || *pos != EAP_TYPE_LEAP) { - wpa_printf(MSG_INFO, "EAP-LEAP: Invalid EAP-Response frame"); - ret->ignore = TRUE; - return NULL; - } - pos++; - - 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 > reqDataLen - sizeof(*resp) - 4) { - wpa_printf(MSG_INFO, "EAP-LEAP: Invalid response " - "(response_len=%d reqDataLen=%lu)", - response_len, (unsigned long) reqDataLen); - 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); - - nt_password_hash(password, password_len, pw_hash); - hash_nt_password_hash(pw_hash, pw_hash_hash); - 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 u8 * eap_leap_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - const struct eap_hdr *eap; - size_t len, 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; - } - - eap = (const struct eap_hdr *) reqData; - - if (reqDataLen < sizeof(*eap) || - (len = be_to_host16(eap->length)) > reqDataLen) { - 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, len, - respDataLen); - case EAP_CODE_SUCCESS: - return eap_leap_process_success(sm, priv, ret, reqData, - respDataLen); - case EAP_CODE_RESPONSE: - return eap_leap_process_response(sm, priv, ret, reqData, len); - 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; - - if (data->state != LEAP_DONE) - return NULL; - - password = eap_get_config_password(sm, &password_len); - if (password == NULL) - return NULL; - - key = os_malloc(LEAP_KEY_LEN); - if (key == NULL) - return NULL; - - nt_password_hash(password, password_len, pw_hash); - hash_nt_password_hash(pw_hash, pw_hash_hash); - 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/contrib/wpa_supplicant/eap_md5.c b/contrib/wpa_supplicant/eap_md5.c deleted file mode 100644 index 5dc16854c938..000000000000 --- a/contrib/wpa_supplicant/eap_md5.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - * EAP peer method: EAP-MD5 (RFC 3748 and RFC 1994) - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "md5.h" -#include "crypto.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 u8 * eap_md5_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - const struct eap_hdr *req; - struct eap_hdr *resp; - const u8 *pos, *challenge, *password; - u8 *rpos; - size_t len, challenge_len, password_len; - const u8 *addr[3]; - size_t elen[3]; - - 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, reqDataLen, &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) - */ - req = (const struct eap_hdr *) reqData; - 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_UNCOND_SUCC; - ret->allowNotifications = TRUE; - - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MD5, respDataLen, - 1 + MD5_MAC_LEN, EAP_CODE_RESPONSE, - req->identifier, &rpos); - if (resp == NULL) - return NULL; - - /* - * CHAP Response: - * Value-Size (1 octet) | Value(Response) | Name(optional) - */ - *rpos++ = MD5_MAC_LEN; - - addr[0] = &resp->identifier; - elen[0] = 1; - addr[1] = password; - elen[1] = password_len; - addr[2] = challenge; - elen[2] = challenge_len; - md5_vector(3, addr, elen, rpos); - wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Response", rpos, MD5_MAC_LEN); - - return (u8 *) 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/contrib/wpa_supplicant/eap_methods.c b/contrib/wpa_supplicant/eap_methods.c deleted file mode 100644 index 53c7e629d0b7..000000000000 --- a/contrib/wpa_supplicant/eap_methods.c +++ /dev/null @@ -1,500 +0,0 @@ -/* - * EAP peer: Method registration - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 <dlfcn.h> -#endif /* CONFIG_DYNAMIC_EAP_METHODS */ - -#include "common.h" -#include "eap_i.h" -#include "eap_methods.h" - - -static struct eap_method *eap_methods = NULL; - - -/** - * eap_sm_get_eap_methods - 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_sm_get_eap_methods(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_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_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_register_methods - Register statically linked EAP peer methods - * Returns: 0 on success, -1 on failure - * - * This function is called at program initialization to register all EAP peer - * methods that were linked in statically. - */ -int eap_peer_register_methods(void) -{ - int ret = 0; - -#ifdef EAP_MD5 - if (ret == 0) { - int eap_peer_md5_register(void); - ret = eap_peer_md5_register(); - } -#endif /* EAP_MD5 */ - -#ifdef EAP_TLS - if (ret == 0) { - int eap_peer_tls_register(void); - ret = eap_peer_tls_register(); - } -#endif /* EAP_TLS */ - -#ifdef EAP_MSCHAPv2 - if (ret == 0) { - int eap_peer_mschapv2_register(void); - ret = eap_peer_mschapv2_register(); - } -#endif /* EAP_MSCHAPv2 */ - -#ifdef EAP_PEAP - if (ret == 0) { - int eap_peer_peap_register(void); - ret = eap_peer_peap_register(); - } -#endif /* EAP_PEAP */ - -#ifdef EAP_TTLS - if (ret == 0) { - int eap_peer_ttls_register(void); - ret = eap_peer_ttls_register(); - } -#endif /* EAP_TTLS */ - -#ifdef EAP_GTC - if (ret == 0) { - int eap_peer_gtc_register(void); - ret = eap_peer_gtc_register(); - } -#endif /* EAP_GTC */ - -#ifdef EAP_OTP - if (ret == 0) { - int eap_peer_otp_register(void); - ret = eap_peer_otp_register(); - } -#endif /* EAP_OTP */ - -#ifdef EAP_SIM - if (ret == 0) { - int eap_peer_sim_register(void); - ret = eap_peer_sim_register(); - } -#endif /* EAP_SIM */ - -#ifdef EAP_LEAP - if (ret == 0) { - int eap_peer_leap_register(void); - ret = eap_peer_leap_register(); - } -#endif /* EAP_LEAP */ - -#ifdef EAP_PSK - if (ret == 0) { - int eap_peer_psk_register(void); - ret = eap_peer_psk_register(); - } -#endif /* EAP_PSK */ - -#ifdef EAP_AKA - if (ret == 0) { - int eap_peer_aka_register(void); - ret = eap_peer_aka_register(); - } -#endif /* EAP_AKA */ - -#ifdef EAP_FAST - if (ret == 0) { - int eap_peer_fast_register(void); - ret = eap_peer_fast_register(); - } -#endif /* EAP_FAST */ - -#ifdef EAP_PAX - if (ret == 0) { - int eap_peer_pax_register(void); - ret = eap_peer_pax_register(); - } -#endif /* EAP_PAX */ - -#ifdef EAP_SAKE - if (ret == 0) { - int eap_peer_sake_register(void); - ret = eap_peer_sake_register(); - } -#endif /* EAP_SAKE */ - -#ifdef EAP_GPSK - if (ret == 0) { - int eap_peer_gpsk_register(void); - ret = eap_peer_gpsk_register(); - } -#endif /* EAP_GPSK */ - -#ifdef EAP_VENDOR_TEST - if (ret == 0) { - int eap_peer_vendor_test_register(void); - ret = eap_peer_vendor_test_register(); - } -#endif /* EAP_VENDOR_TEST */ - - return ret; -} - - -/** - * 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/contrib/wpa_supplicant/eap_methods.h b/contrib/wpa_supplicant/eap_methods.h deleted file mode 100644 index 625c4d16b8dc..000000000000 --- a/contrib/wpa_supplicant/eap_methods.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * EAP peer: Method registration - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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_defs.h" - -const struct eap_method * eap_sm_get_eap_methods(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_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); -int eap_peer_register_methods(void); -void eap_peer_unregister_methods(void); - -#else /* IEEE8021X_EAPOL */ - -static inline EapType eap_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) -{ -} - -#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 */ - -#endif /* EAP_METHODS_H */ diff --git a/contrib/wpa_supplicant/eap_mschapv2.c b/contrib/wpa_supplicant/eap_mschapv2.c deleted file mode 100644 index 26c835148980..000000000000 --- a/contrib/wpa_supplicant/eap_mschapv2.c +++ /dev/null @@ -1,944 +0,0 @@ -/* - * EAP peer method: EAP-MSCHAPV2 (draft-kamath-pppext-eap-mschapv2-00.txt) - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "eap_i.h" -#include "config_ssid.h" -#include "ms_funcs.h" -#include "wpa_ctrl.h" - - -#define MSCHAPV2_CHAL_LEN 16 -#define MSCHAPV2_NT_RESPONSE_LEN 24 - -#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[20]; - 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 full_key; - - int phase2; - u8 master_key[16]; - int master_key_valid; - int success; - - u8 *prev_challenge; - size_t prev_challenge_len; -}; - - -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; - - data->full_key = sm->mschapv2_full_key; - - if (sm->peer_challenge) { - data->full_key = 1; - 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); - os_free(data->prev_challenge); - os_free(data); -} - - -static const u8 * eap_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; -} - - -static void eap_mschapv2_derive_response( - struct eap_mschapv2_data *data, - const u8 *username, size_t username_len, - const u8 *password, size_t password_len, - const u8 *auth_challenge, const u8 *peer_challenge, - u8 *nt_response) -{ - u8 password_hash[16], password_hash_hash[16]; - - wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: auth_challenge", - auth_challenge, MSCHAPV2_CHAL_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: peer_challenge", - peer_challenge, MSCHAPV2_CHAL_LEN); - wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: username", - username, username_len); - wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-MSCHAPV2: password", - password, password_len); - generate_nt_response(auth_challenge, peer_challenge, - username, username_len, - password, password_len, nt_response); - wpa_hexdump(MSG_DEBUG, "EAP-MSCHAPV2: response", 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(password, password_len, - peer_challenge, auth_challenge, - username, username_len, 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(password, password_len, password_hash); - hash_nt_password_hash(password_hash, password_hash_hash); - get_master_key(password_hash_hash, nt_response, data->master_key); - data->master_key_valid = 1; -} - - -static u8 * eap_mschapv2_challenge_reply(struct eap_sm *sm, - struct eap_mschapv2_data *data, u8 id, - u8 mschapv2_id, - const u8 *auth_challenge, - size_t *respDataLen) -{ - struct eap_hdr *resp; - struct eap_mschapv2_hdr *ms; - u8 *rpos, *peer_challenge; - int ms_len; - struct ms_response *r; - size_t username_len, identity_len, password_len; - const u8 *username, *identity, *password; - - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Generating Challenge Response"); - - identity = eap_get_config_identity(sm, &identity_len); - password = eap_get_config_password(sm, &password_len); - if (identity == NULL || password == NULL) - return NULL; - - username_len = identity_len; - username = eap_mschapv2_remove_domain(identity, &username_len); - - ms_len = sizeof(*ms) + 1 + sizeof(*r) + identity_len; - resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respDataLen, - ms_len, EAP_CODE_RESPONSE, id, &rpos); - if (resp == NULL) - return NULL; - - ms = (struct eap_mschapv2_hdr *) rpos; - 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); - rpos = (u8 *) (ms + 1); - *rpos++ = sizeof(*r); /* Value-Size */ - - /* Response */ - r = (struct ms_response *) rpos; - 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 (os_get_random(peer_challenge, MSCHAPV2_CHAL_LEN)) { - os_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; - } - eap_mschapv2_derive_response(data, username, username_len, - password, password_len, - auth_challenge, peer_challenge, - r->nt_response); - - r->flags = 0; /* reserved, must be zero */ - - os_memcpy((u8 *) (r + 1), identity, identity_len); - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: TX identifier %d mschapv2_id %d " - "(response)", resp->identifier, ms->mschapv2_id); - return (u8 *) resp; -} - - -/** - * eap_mschapv2_process - Process an EAP-MSCHAPv2 challenge message - * @sm: Pointer to EAP state machine allocated with eap_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 - * @respDataLen: Length of the returned EAP response - * Returns: Pointer to allocated EAP response packet (eapRespData) or %NULL if - * no reply available - */ -static u8 * 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 *respDataLen) -{ - 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, respDataLen); -} - - -static void eap_mschapv2_password_changed(struct eap_sm *sm, - struct eap_mschapv2_data *data) -{ - struct wpa_ssid *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); - config->password = config->new_password; - config->new_password = NULL; - config->password_len = config->new_password_len; - config->new_password_len = 0; - } -} - - -/** - * eap_mschapv2_process - Process an EAP-MSCHAPv2 success message - * @sm: Pointer to EAP state machine allocated with eap_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 - * @respDataLen: Length of the returned EAP response - * Returns: Pointer to allocated EAP response packet (eapRespData) or %NULL if - * no reply available - */ -static u8 * 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, size_t *respDataLen) -{ - struct eap_hdr *resp; - struct eap_mschapv2_hdr *ms; - const u8 *pos; - u8 recv_response[20]; - size_t len; - u8 *rpos; - - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Received success"); - len = req_len - sizeof(*req); - pos = (const u8 *) (req + 1); - if (!data->auth_response_valid || len < 42 || - pos[0] != 'S' || pos[1] != '=' || - hexstr2bin((char *) (pos + 2), recv_response, 20) || - os_memcmp(data->auth_response, recv_response, 20) != 0) { - wpa_printf(MSG_WARNING, "EAP-MSCHAPV2: Invalid authenticator " - "response in success request"); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - return NULL; - } - pos += 42; - len -= 42; - 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, respDataLen, - 1, EAP_CODE_RESPONSE, id, &rpos); - if (resp == NULL) { - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Failed to allocate " - "buffer for success response"); - ret->ignore = TRUE; - return NULL; - } - - ms = (struct eap_mschapv2_hdr *) rpos; - ms->op_code = MSCHAPV2_OP_SUCCESS; - - 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 (u8 *) 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 wpa_ssid *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 u8 * 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, size_t *respDataLen) -{ - struct eap_hdr *resp; - int ms_len; - const u8 *username, *password, *new_password; - u8 *pos; - size_t username_len, password_len, new_password_len; - struct eap_mschapv2_hdr *ms; - struct ms_change_password *cp; - - username = eap_get_config_identity(sm, &username_len); - password = eap_get_config_password(sm, &password_len); - new_password = eap_get_config_new_password(sm, &new_password_len); - if (username == NULL || password == NULL || new_password == NULL) - return NULL; - - username = eap_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, respDataLen, - ms_len, EAP_CODE_RESPONSE, id, &pos); - if (resp == NULL) - return NULL; - - ms = (struct eap_mschapv2_hdr *) pos; - ms->op_code = MSCHAPV2_OP_CHANGE_PASSWORD; - ms->mschapv2_id = req->mschapv2_id + 1; - WPA_PUT_BE16(ms->ms_length, ms_len); - cp = (struct ms_change_password *) (ms + 1); - - /* Encrypted-Password */ - new_password_encrypted_with_old_nt_password_hash( - new_password, new_password_len, - password, password_len, cp->encr_password); - - /* Encrypted-Hash */ - old_nt_password_hash_encrypted_with_new_nt_password_hash( - new_password, new_password_len, - password, password_len, cp->encr_hash); - - /* Peer-Challenge */ - if (os_get_random(cp->peer_challenge, MSCHAPV2_CHAL_LEN)) { - os_free(resp); - return NULL; - } - - /* 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; - - /* Flags */ - os_memset(cp->flags, 0, 2); - - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: TX identifier %d mschapv2_id %d " - "(change pw)", resp->identifier, ms->mschapv2_id); - - return (u8 *) resp; -} - - -/** - * eap_mschapv2_process - Process an EAP-MSCHAPv2 failure message - * @sm: Pointer to EAP state machine allocated with eap_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 - * @respDataLen: Length of the returned EAP response - * Returns: Pointer to allocated EAP response packet (eapRespData) or %NULL if - * no reply available - */ -static u8 * 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, size_t *respDataLen) -{ - struct eap_hdr *resp; - const u8 *msdata = (const u8 *) (req + 1); - char *buf; - size_t len = req_len - sizeof(*req); - int retry = 0; - struct eap_mschapv2_hdr *ms; - u8 *pos; - - 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 wpa_ssid *config = eap_get_config(sm); - if (config && config->new_password) - return eap_mschapv2_change_password(sm, data, ret, req, - id, respDataLen); - 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, respDataLen, - 1, EAP_CODE_RESPONSE, id, &pos); - if (resp == NULL) - return NULL; - - ms = (struct eap_mschapv2_hdr *) pos; - ms->op_code = MSCHAPV2_OP_FAILURE; - - return (u8 *) 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 u8 *reqData, size_t reqDataLen) -{ - /* - * Store a copy of the challenge message, so that it can be processed - * again in case retry is allowed after a possible failure. - */ - os_free(data->prev_challenge); - data->prev_challenge = os_malloc(reqDataLen); - if (data->prev_challenge) { - data->prev_challenge_len = reqDataLen; - os_memcpy(data->prev_challenge, reqData, reqDataLen); - } -} - - -/** - * eap_mschapv2_process - Process an EAP-MSCHAPv2 request - * @sm: Pointer to EAP state machine allocated with eap_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) - * @reqDataLen: Length of the EAP request - * @respDataLen: Length of the returned EAP response - * Returns: Pointer to allocated EAP response packet (eapRespData) or %NULL if - * no reply available - */ -static u8 * eap_mschapv2_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - struct eap_mschapv2_data *data = priv; - struct wpa_ssid *config = eap_get_config(sm); - const struct eap_hdr *req; - const struct eap_mschapv2_hdr *ms; - int using_prev_challenge = 0; - const u8 *pos; - size_t len; - - 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; - reqDataLen = data->prev_challenge_len; - using_prev_challenge = 1; - config->mschapv2_retry = 0; - } - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, - reqData, reqDataLen, &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; - } - - req = (const struct eap_hdr *) reqData; - wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: RX identifier %d mschapv2_id %d", - req->identifier, ms->mschapv2_id); - - switch (ms->op_code) { - case MSCHAPV2_OP_CHALLENGE: - if (!using_prev_challenge) - eap_mschapv2_copy_challenge(data, reqData, reqDataLen); - return eap_mschapv2_challenge(sm, data, ret, ms, len, - req->identifier, respDataLen); - case MSCHAPV2_OP_SUCCESS: - return eap_mschapv2_success(sm, data, ret, ms, len, - req->identifier, respDataLen); - case MSCHAPV2_OP_FAILURE: - return eap_mschapv2_failure(sm, data, ret, ms, len, - req->identifier, respDataLen); - 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; - - if (data->full_key) { - /* EAP-FAST needs both send and receive keys */ - key_len = 2 * MSCHAPV2_KEY_LEN; - } else { - key_len = MSCHAPV2_KEY_LEN; - } - - key = os_malloc(key_len); - if (key == NULL) - return NULL; - - if (data->full_key) { - get_asymetric_start_key(data->master_key, key, - MSCHAPV2_KEY_LEN, 0, 0); - get_asymetric_start_key(data->master_key, - key + MSCHAPV2_KEY_LEN, - MSCHAPV2_KEY_LEN, 1, 0); - } else { - get_asymetric_start_key(data->master_key, key, - MSCHAPV2_KEY_LEN, 1, 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/contrib/wpa_supplicant/eap_otp.c b/contrib/wpa_supplicant/eap_otp.c deleted file mode 100644 index 4cb131f30b4e..000000000000 --- a/contrib/wpa_supplicant/eap_otp.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * EAP peer method: EAP-OTP (RFC 3748) - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "config_ssid.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 u8 * eap_otp_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - const struct eap_hdr *req; - struct eap_hdr *resp; - const u8 *pos, *password; - u8 *rpos; - size_t password_len, len; - int otp; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_OTP, - reqData, reqDataLen, &len); - if (pos == NULL) { - ret->ignore = TRUE; - return NULL; - } - req = (const struct eap_hdr *) reqData; - 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, respDataLen, - password_len, EAP_CODE_RESPONSE, req->identifier, - &rpos); - if (resp == NULL) - return NULL; - os_memcpy(rpos, 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 (u8 *) 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/contrib/wpa_supplicant/eap_pax.c b/contrib/wpa_supplicant/eap_pax.c deleted file mode 100644 index d9d937dc1fbc..000000000000 --- a/contrib/wpa_supplicant/eap_pax.c +++ /dev/null @@ -1,551 +0,0 @@ -/* - * EAP peer method: EAP-PAX (RFC 4746) - * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "config_ssid.h" -#include "eap_pax_common.h" -#include "sha1.h" -#include "crypto.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 wpa_ssid *config = eap_get_config(sm); - struct eap_pax_data *data; - - if (config == NULL || !config->nai || - (!config->eappsk && !config->password)) { - wpa_printf(MSG_INFO, "EAP-PAX: CID (nai) or key " - "(eappsk/password) not configured"); - return NULL; - } - - if (config->eappsk && config->eappsk_len != EAP_PAX_AK_LEN) { - wpa_printf(MSG_INFO, "EAP-PAX: incorrect key length (eappsk); " - "expected %d", EAP_PAX_AK_LEN); - return NULL; - } - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = PAX_INIT; - - data->cid = os_malloc(config->nai_len); - if (data->cid == NULL) { - eap_pax_deinit(sm, data); - return NULL; - } - os_memcpy(data->cid, config->nai, config->nai_len); - data->cid_len = config->nai_len; - - if (config->eappsk) { - os_memcpy(data->ak, config->eappsk, EAP_PAX_AK_LEN); - } else { - u8 hash[SHA1_MAC_LEN]; - const unsigned char *addr[1]; - size_t len[1]; - addr[0] = config->password; - len[0] = config->password_len; - sha1_vector(1, addr, len, hash); - os_memcpy(data->ak, hash, 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 eap_pax_hdr * eap_pax_alloc_resp(const struct eap_pax_hdr *req, - u16 resp_len, u8 op_code) -{ - struct eap_pax_hdr *resp; - - resp = os_malloc(resp_len); - if (resp == NULL) - return NULL; - resp->code = EAP_CODE_RESPONSE; - resp->identifier = req->identifier; - resp->length = host_to_be16(resp_len); - resp->type = EAP_TYPE_PAX; - resp->op_code = op_code; - resp->flags = 0; - resp->mac_id = req->mac_id; - resp->dh_group_id = req->dh_group_id; - resp->public_key_id = req->public_key_id; - return resp; -} - - -static u8 * eap_pax_process_std_1(struct eap_pax_data *data, - struct eap_method_ret *ret, - const u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - const struct eap_pax_hdr *req; - struct eap_pax_hdr *resp; - const u8 *pos; - u8 *rpos; - size_t left; - - wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-1 (received)"); - req = (const struct eap_pax_hdr *) reqData; - - 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 = reqDataLen - 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 (hostapd_get_rand(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)"); - - *respDataLen = sizeof(*resp) + 2 + EAP_PAX_RAND_LEN + - 2 + data->cid_len + 2 + EAP_PAX_MAC_LEN + EAP_PAX_ICV_LEN; - resp = eap_pax_alloc_resp(req, *respDataLen, EAP_PAX_OP_STD_2); - if (resp == NULL) - return NULL; - - rpos = (u8 *) (resp + 1); - *rpos++ = 0; - *rpos++ = EAP_PAX_RAND_LEN; - os_memcpy(rpos, data->rand.r.y, EAP_PAX_RAND_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: B = Y (client rand)", - rpos, EAP_PAX_RAND_LEN); - rpos += EAP_PAX_RAND_LEN; - - WPA_PUT_BE16(rpos, data->cid_len); - rpos += 2; - os_memcpy(rpos, data->cid, data->cid_len); - wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-PAX: CID", rpos, data->cid_len); - rpos += data->cid_len; - - *rpos++ = 0; - *rpos++ = 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); - rpos += EAP_PAX_MAC_LEN; - - /* Optional ADE could be added here, if needed */ - - eap_pax_mac(req->mac_id, data->ick, EAP_PAX_ICK_LEN, - (u8 *) resp, *respDataLen - EAP_PAX_ICV_LEN, - NULL, 0, NULL, 0, rpos); - wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", rpos, EAP_PAX_ICV_LEN); - 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 (u8 *) resp; -} - - -static u8 * eap_pax_process_std_3(struct eap_pax_data *data, - struct eap_method_ret *ret, - const u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - const struct eap_pax_hdr *req; - struct eap_pax_hdr *resp; - u8 *rpos, mac[EAP_PAX_MAC_LEN]; - const u8 *pos; - size_t left; - - wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-3 (received)"); - req = (const struct eap_pax_hdr *) reqData; - - 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 = reqDataLen - 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)"); - - *respDataLen = sizeof(*resp) + EAP_PAX_ICV_LEN; - resp = eap_pax_alloc_resp(req, *respDataLen, EAP_PAX_OP_ACK); - if (resp == NULL) - return NULL; - - rpos = (u8 *) (resp + 1); - - /* Optional ADE could be added here, if needed */ - - eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN, - (u8 *) resp, *respDataLen - 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 (u8 *) resp; -} - - -static u8 * eap_pax_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - struct eap_pax_data *data = priv; - const struct eap_pax_hdr *req; - u8 *resp, icvbuf[EAP_PAX_ICV_LEN]; - const u8 *icv, *pos; - size_t len; - u16 flen; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PAX, - reqData, reqDataLen, &len); - if (pos == NULL || len < EAP_PAX_ICV_LEN) { - ret->ignore = TRUE; - return NULL; - } - req = (const struct eap_pax_hdr *) reqData; - flen = be_to_host16(req->length) - 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, - reqData, flen, NULL, 0, NULL, 0, icvbuf); - } else { - eap_pax_mac(req->mac_id, data->ick, EAP_PAX_ICK_LEN, - reqData, flen, 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, reqData, flen, - respDataLen); - break; - case EAP_PAX_OP_STD_3: - resp = eap_pax_process_std_3(data, ret, reqData, flen, - respDataLen); - 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/contrib/wpa_supplicant/eap_pax_common.c b/contrib/wpa_supplicant/eap_pax_common.c deleted file mode 100644 index 80110469dcc3..000000000000 --- a/contrib/wpa_supplicant/eap_pax_common.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * EAP server/peer: EAP-PAX shared routines - * Copyright (c) 2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "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/contrib/wpa_supplicant/eap_pax_common.h b/contrib/wpa_supplicant/eap_pax_common.h deleted file mode 100644 index bbad5e4052ff..000000000000 --- a/contrib/wpa_supplicant/eap_pax_common.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * EAP server/peer: EAP-PAX shared routines - * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 code; - u8 identifier; - u16 length; /* including code, identifier, and length */ - u8 type; /* EAP_TYPE_PAX */ - 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/contrib/wpa_supplicant/eap_peap.c b/contrib/wpa_supplicant/eap_peap.c deleted file mode 100644 index 12bd8d8e2f9e..000000000000 --- a/contrib/wpa_supplicant/eap_peap.c +++ /dev/null @@ -1,895 +0,0 @@ -/* - * EAP peer method: EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-07.txt) - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "config_ssid.h" -#include "tls.h" -#include "eap_tlv.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-07.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 */ - u8 *key_data; - - u8 *pending_phase2_req; - size_t pending_phase2_req_len; -}; - - -static void * eap_peap_init(struct eap_sm *sm) -{ - struct eap_peap_data *data; - struct wpa_ssid *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; - - if (config && config->phase1) { - char *pos = os_strstr(config->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(config->phase1, "peaplabel=1")) { - data->force_new_label = 1; - wpa_printf(MSG_DEBUG, "EAP-PEAP: Force new label for " - "key derivation"); - } - - if (os_strstr(config->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(config->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(config->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 (config && config->phase2) { - char *start, *pos, *buf; - struct eap_method_type *methods = NULL, *_methods; - u8 method; - size_t num_methods = 0; - start = buf = os_strdup(config->phase2); - if (buf == NULL) { - eap_peap_deinit(sm, data); - return NULL; - } - while (start && *start != '\0') { - int vendor; - pos = os_strstr(start, "auth="); - if (pos == NULL) - break; - if (start != pos && *(pos - 1) != ' ') { - start = pos + 5; - continue; - } - - start = pos + 5; - 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, "EAP-PEAP: Unsupported " - "Phase2 method '%s'", start); - } else { - num_methods++; - _methods = os_realloc( - methods, - num_methods * sizeof(*methods)); - if (_methods == NULL) { - os_free(methods); - os_free(buf); - eap_peap_deinit(sm, data); - return NULL; - } - methods = _methods; - methods[num_methods - 1].vendor = vendor; - methods[num_methods - 1].method = method; - } - - start = pos; - } - os_free(buf); - data->phase2_types = methods; - data->num_phase2_types = num_methods; - } - if (data->phase2_types == NULL) { - data->phase2_types = - eap_get_phase2_types(config, &data->num_phase2_types); - } - if (data->phase2_types == NULL) { - wpa_printf(MSG_ERROR, "EAP-PEAP: No Phase2 method available"); - eap_peap_deinit(sm, data); - return NULL; - } - wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Phase2 EAP types", - (u8 *) data->phase2_types, - data->num_phase2_types * sizeof(struct eap_method_type)); - data->phase2_type.vendor = EAP_VENDOR_IETF; - data->phase2_type.method = EAP_TYPE_NONE; - - if (eap_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_tls_ssl_deinit(sm, &data->ssl); - os_free(data->key_data); - os_free(data->pending_phase2_req); - os_free(data); -} - - -static int eap_peap_encrypt(struct eap_sm *sm, struct eap_peap_data *data, - int id, const u8 *plain, size_t plain_len, - u8 **out_data, size_t *out_len) -{ - int res; - u8 *pos; - struct eap_hdr *resp; - - /* TODO: add support for fragmentation, if needed. This will need to - * add TLS Message Length field, if the frame is fragmented. - * Note: Microsoft IAS did not seem to like TLS Message Length with - * PEAP/MSCHAPv2. */ - resp = os_malloc(sizeof(struct eap_hdr) + 2 + data->ssl.tls_out_limit); - if (resp == NULL) - return -1; - - resp->code = EAP_CODE_RESPONSE; - resp->identifier = id; - - pos = (u8 *) (resp + 1); - *pos++ = EAP_TYPE_PEAP; - *pos++ = data->peap_version; - - res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn, - plain, plain_len, - pos, data->ssl.tls_out_limit); - if (res < 0) { - wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt Phase 2 " - "data"); - os_free(resp); - return -1; - } - - *out_len = sizeof(struct eap_hdr) + 2 + res; - resp->length = host_to_be16(*out_len); - *out_data = (u8 *) resp; - return 0; -} - - -static int eap_peap_phase2_nak(struct eap_peap_data *data, struct eap_hdr *hdr, - u8 **resp, size_t *resp_len) -{ - struct eap_hdr *resp_hdr; - u8 *pos = (u8 *) (hdr + 1); - size_t i; - - /* TODO: add support for expanded Nak */ - wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Request: Nak type=%d", *pos); - wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Allowed Phase2 EAP types", - (u8 *) data->phase2_types, - data->num_phase2_types * sizeof(struct eap_method_type)); - *resp_len = sizeof(struct eap_hdr) + 1; - *resp = os_malloc(*resp_len + data->num_phase2_types); - if (*resp == NULL) - return -1; - - resp_hdr = (struct eap_hdr *) (*resp); - resp_hdr->code = EAP_CODE_RESPONSE; - resp_hdr->identifier = hdr->identifier; - pos = (u8 *) (resp_hdr + 1); - *pos++ = EAP_TYPE_NAK; - for (i = 0; i < data->num_phase2_types; i++) { - if (data->phase2_types[i].vendor == EAP_VENDOR_IETF && - data->phase2_types[i].method < 256) { - (*resp_len)++; - *pos++ = data->phase2_types[i].method; - } - } - resp_hdr->length = host_to_be16(*resp_len); - - return 0; -} - - -static int eap_peap_phase2_request(struct eap_sm *sm, - struct eap_peap_data *data, - struct eap_method_ret *ret, - struct eap_hdr *hdr, - u8 **resp, size_t *resp_len) -{ - size_t len = be_to_host16(hdr->length); - u8 *pos; - struct eap_method_ret iret; - struct wpa_ssid *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, resp_len, 1); - break; - case EAP_TYPE_TLV: - os_memset(&iret, 0, sizeof(iret)); - if (eap_tlv_process(sm, &iret, hdr, resp, resp_len, - 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; - 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_peap_phase2_nak(data, hdr, resp, resp_len)) - return -1; - return 0; - } - - if (data->phase2_priv == NULL) { - data->phase2_method = eap_sm_get_eap_methods( - 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, (u8 *) hdr, len, - resp_len); - 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)) { - os_free(data->pending_phase2_req); - data->pending_phase2_req = os_malloc(len); - if (data->pending_phase2_req) { - os_memcpy(data->pending_phase2_req, hdr, len); - data->pending_phase2_req_len = 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 u8 *in_data, size_t in_len, - u8 **out_data, size_t *out_len) -{ - u8 *in_decrypted; - int res, skip_change = 0; - struct eap_hdr *hdr, *rhdr; - u8 *resp = NULL; - size_t resp_len, len_decrypted, len, buf_len; - const u8 *msg; - size_t msg_len; - int need_more_input; - - wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for" - " Phase 2", (unsigned long) in_len); - - 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. */ - os_free(data->ssl.tls_in); - data->ssl.tls_in = NULL; - data->ssl.tls_in_len = 0; - data->ssl.tls_in_left = 0; - data->ssl.tls_in_total = 0; - in_decrypted = data->pending_phase2_req; - data->pending_phase2_req = NULL; - len_decrypted = data->pending_phase2_req_len; - skip_change = 1; - goto continue_req; - } - - msg = eap_tls_data_reassemble(sm, &data->ssl, in_data, in_len, - &msg_len, &need_more_input); - if (msg == NULL) - return need_more_input ? 1 : -1; - - if (in_len == 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; - } - - buf_len = in_len; - if (data->ssl.tls_in_total > buf_len) - buf_len = data->ssl.tls_in_total; - in_decrypted = os_malloc(buf_len); - if (in_decrypted == NULL) { - os_free(data->ssl.tls_in); - data->ssl.tls_in = NULL; - data->ssl.tls_in_len = 0; - wpa_printf(MSG_WARNING, "EAP-PEAP: failed to allocate memory " - "for decryption"); - return -1; - } - - res = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn, - msg, msg_len, in_decrypted, buf_len); - os_free(data->ssl.tls_in); - data->ssl.tls_in = NULL; - data->ssl.tls_in_len = 0; - if (res < 0) { - wpa_printf(MSG_INFO, "EAP-PEAP: Failed to decrypt Phase 2 " - "data"); - os_free(in_decrypted); - return 0; - } - len_decrypted = res; - -continue_req: - wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP", in_decrypted, - len_decrypted); - - hdr = (struct eap_hdr *) in_decrypted; - if (len_decrypted == 5 && hdr->code == EAP_CODE_REQUEST && - be_to_host16(hdr->length) == 5 && - in_decrypted[4] == EAP_TYPE_IDENTITY) { - /* At least FreeRADIUS seems to send full EAP header with - * EAP Request Identity */ - skip_change = 1; - } - if (len_decrypted >= 5 && hdr->code == EAP_CODE_REQUEST && - in_decrypted[4] == EAP_TYPE_TLV) { - skip_change = 1; - } - - if (data->peap_version == 0 && !skip_change) { - struct eap_hdr *nhdr = os_malloc(sizeof(struct eap_hdr) + - len_decrypted); - if (nhdr == NULL) { - os_free(in_decrypted); - return 0; - } - os_memcpy((u8 *) (nhdr + 1), in_decrypted, len_decrypted); - os_free(in_decrypted); - nhdr->code = req->code; - nhdr->identifier = req->identifier; - nhdr->length = host_to_be16(sizeof(struct eap_hdr) + - len_decrypted); - - len_decrypted += sizeof(struct eap_hdr); - in_decrypted = (u8 *) nhdr; - } - hdr = (struct eap_hdr *) in_decrypted; - if (len_decrypted < sizeof(*hdr)) { - os_free(in_decrypted); - wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 " - "EAP frame (len=%lu)", - (unsigned long) len_decrypted); - return 0; - } - len = be_to_host16(hdr->length); - if (len > len_decrypted) { - os_free(in_decrypted); - wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in " - "Phase 2 EAP frame (len=%lu hdr->length=%lu)", - (unsigned long) len_decrypted, (unsigned long) len); - return 0; - } - if (len < len_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) len_decrypted); - if (sm->workaround && len == 4 && len_decrypted == 5 && - in_decrypted[4] == EAP_TYPE_IDENTITY) { - /* Radiator 3.9 seems to set Phase 2 EAP header to use - * incorrect length for the EAP-Request Identity - * packet, so fix the inner header to interoperate.. - * This was fixed in 2004-06-23 patch for Radiator and - * this workaround can be removed at some point. */ - wpa_printf(MSG_INFO, "EAP-PEAP: workaround -> replace " - "Phase 2 EAP header len (%lu) with real " - "decrypted len (%lu)", - (unsigned long) len, - (unsigned long) len_decrypted); - len = len_decrypted; - hdr->length = host_to_be16(len); - } - } - 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, hdr, - &resp, &resp_len)) { - os_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; - os_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) { - os_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_len = sizeof(struct eap_hdr); - resp = os_zalloc(resp_len); - if (resp) { - rhdr = (struct eap_hdr *) resp; - rhdr->code = EAP_CODE_SUCCESS; - rhdr->identifier = hdr->identifier; - rhdr->length = host_to_be16(resp_len); - } - } 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_len = sizeof(struct eap_hdr); - resp = os_zalloc(resp_len); - if (resp) { - rhdr = (struct eap_hdr *) resp; - rhdr->code = EAP_CODE_FAILURE; - rhdr->identifier = hdr->identifier; - rhdr->length = host_to_be16(resp_len); - } - break; - default: - wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in " - "Phase 2 EAP header", hdr->code); - break; - } - - os_free(in_decrypted); - - if (resp) { - u8 *resp_pos; - size_t resp_send_len; - int skip_change2 = 0; - - wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: Encrypting Phase 2 data", - resp, resp_len); - /* PEAP version changes */ - if (resp_len >= 5 && resp[0] == EAP_CODE_RESPONSE && - resp[4] == EAP_TYPE_TLV) - skip_change2 = 1; - if (data->peap_version == 0 && !skip_change2) { - resp_pos = resp + sizeof(struct eap_hdr); - resp_send_len = resp_len - sizeof(struct eap_hdr); - } else { - resp_pos = resp; - resp_send_len = resp_len; - } - - if (eap_peap_encrypt(sm, data, req->identifier, - resp_pos, resp_send_len, - out_data, out_len)) { - wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt " - "a Phase 2 frame"); - } - os_free(resp); - } - - return 0; -} - - -static u8 * eap_peap_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - const struct eap_hdr *req; - size_t left; - int res; - u8 flags, *resp, id; - const u8 *pos; - struct eap_peap_data *data = priv; - - pos = eap_tls_process_init(sm, &data->ssl, EAP_TYPE_PEAP, ret, - reqData, reqDataLen, &left, &flags); - if (pos == NULL) - return NULL; - req = (const struct eap_hdr *) 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_PEAP_VERSION_MASK, - data->peap_version); - if ((flags & EAP_PEAP_VERSION_MASK) < data->peap_version) - data->peap_version = flags & EAP_PEAP_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) { - res = eap_peap_decrypt(sm, data, ret, req, pos, left, - &resp, respDataLen); - } else { - res = eap_tls_process_helper(sm, &data->ssl, EAP_TYPE_PEAP, - data->peap_version, id, pos, left, - &resp, respDataLen); - - 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_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) { - /* - * Application data included in the handshake message. - */ - os_free(data->pending_phase2_req); - data->pending_phase2_req = resp; - data->pending_phase2_req_len = *respDataLen; - resp = NULL; - *respDataLen = 0; - res = eap_peap_decrypt(sm, data, ret, req, pos, left, - &resp, respDataLen); - } - } - - if (ret->methodState == METHOD_DONE) { - ret->allowNotifications = FALSE; - } - - if (res == 1) { - return eap_tls_build_ack(&data->ssl, respDataLen, 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; - os_free(data->pending_phase2_req); - data->pending_phase2_req = NULL; -} - - -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_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; - 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_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; - 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/contrib/wpa_supplicant/eap_psk.c b/contrib/wpa_supplicant/eap_psk.c deleted file mode 100644 index e07b25b026a9..000000000000 --- a/contrib/wpa_supplicant/eap_psk.c +++ /dev/null @@ -1,468 +0,0 @@ -/* - * EAP peer method: EAP-PSK (RFC 4764) - * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "eap_i.h" -#include "config_ssid.h" -#include "md5.h" -#include "aes_wrap.h" -#include "eap_psk_common.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 wpa_ssid *config = eap_get_config(sm); - struct eap_psk_data *data; - - if (config == NULL || !config->eappsk) { - wpa_printf(MSG_INFO, "EAP-PSK: pre-shared key not configured"); - return NULL; - } - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - eap_psk_key_setup(config->eappsk, data->ak, data->kdk); - 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; - - if (config->nai) { - data->id_p = os_malloc(config->nai_len); - if (data->id_p) - os_memcpy(data->id_p, config->nai, config->nai_len); - data->id_p_len = config->nai_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 u8 * eap_psk_process_1(struct eap_psk_data *data, - struct eap_method_ret *ret, - const u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - const struct eap_psk_hdr_1 *hdr1; - struct eap_psk_hdr_2 *hdr2; - u8 *resp, *buf, *pos; - size_t buflen; - - wpa_printf(MSG_DEBUG, "EAP-PSK: in INIT state"); - - hdr1 = (const struct eap_psk_hdr_1 *) reqData; - if (reqDataLen < sizeof(*hdr1) || - be_to_host16(hdr1->length) < sizeof(*hdr1) || - be_to_host16(hdr1->length) > reqDataLen) { - wpa_printf(MSG_INFO, "EAP-PSK: Invalid first message " - "length (%lu %d; expected %lu or more)", - (unsigned long) reqDataLen, - be_to_host16(hdr1->length), - (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 = be_to_host16(hdr1->length) - 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 (hostapd_get_rand(data->rand_p, EAP_PSK_RAND_LEN)) { - wpa_printf(MSG_ERROR, "EAP-PSK: Failed to get random data"); - ret->ignore = TRUE; - return NULL; - } - - *respDataLen = sizeof(*hdr2) + data->id_p_len; - resp = os_malloc(*respDataLen); - if (resp == NULL) - return NULL; - hdr2 = (struct eap_psk_hdr_2 *) resp; - hdr2->code = EAP_CODE_RESPONSE; - hdr2->identifier = hdr1->identifier; - hdr2->length = host_to_be16(*respDataLen); - hdr2->type = EAP_TYPE_PSK; - 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); - os_memcpy((u8 *) (hdr2 + 1), 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) { - os_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); - omac1_aes_128(data->ak, buf, buflen, hdr2->mac_p); - 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", - (u8 *) (hdr2 + 1), data->id_p_len); - - data->state = PSK_MAC_SENT; - - return resp; -} - - -static u8 * eap_psk_process_3(struct eap_psk_data *data, - struct eap_method_ret *ret, - const u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - const struct eap_psk_hdr_3 *hdr3; - struct eap_psk_hdr_4 *hdr4; - u8 *resp, *buf, *rpchannel, nonce[16], *decrypted; - const u8 *pchannel, *tag, *msg; - u8 mac[EAP_PSK_MAC_LEN]; - size_t buflen, left, data_len; - int failed = 0; - - wpa_printf(MSG_DEBUG, "EAP-PSK: in MAC_SENT state"); - - hdr3 = (const struct eap_psk_hdr_3 *) reqData; - left = be_to_host16(hdr3->length); - if (left < sizeof(*hdr3) || reqDataLen < left) { - wpa_printf(MSG_INFO, "EAP-PSK: Invalid third message " - "length (%lu %d; expected %lu)", - (unsigned long) reqDataLen, - be_to_host16(hdr3->length), - (unsigned long) sizeof(*hdr3)); - ret->ignore = TRUE; - return NULL; - } - left -= 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); - omac1_aes_128(data->ak, buf, buflen, mac); - 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"); - - eap_psk_derive_keys(data->kdk, data->rand_p, data->tek, - data->msk, data->emsk); - 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", 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), - reqData, 22, 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; - } - - *respDataLen = sizeof(*hdr4) + 4 + 16 + 1; - resp = os_malloc(*respDataLen + 1); - if (resp == NULL) { - os_free(decrypted); - return NULL; - } - hdr4 = (struct eap_psk_hdr_4 *) resp; - hdr4->code = EAP_CODE_RESPONSE; - hdr4->identifier = hdr3->identifier; - hdr4->length = host_to_be16(*respDataLen); - hdr4->type = EAP_TYPE_PSK; - hdr4->flags = EAP_PSK_FLAGS_SET_T(3); /* T=3 */ - os_memcpy(hdr4->rand_s, hdr3->rand_s, EAP_PSK_RAND_LEN); - rpchannel = (u8 *) (hdr4 + 1); - - /* nonce++ */ - inc_byte_array(nonce, sizeof(nonce)); - os_memcpy(rpchannel, nonce + 12, 4); - - data_len = 1; - 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 */ - (*respDataLen)++; - hdr4->length = host_to_be16(*respDataLen); - rpchannel[4 + 16 + 1] = decrypted[1]; - data_len++; - } - } 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); - aes_128_eax_encrypt(data->tek, nonce, sizeof(nonce), resp, 22, - rpchannel + 4 + 16, data_len, rpchannel + 4); - 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 u8 * eap_psk_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - struct eap_psk_data *data = priv; - const u8 *pos; - u8 *resp = NULL; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, - reqData, reqDataLen, &len); - if (pos == NULL) { - ret->ignore = TRUE; - return NULL; - } - len += sizeof(struct eap_hdr) + 1; - - 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, len, - respDataLen); - break; - case PSK_MAC_SENT: - resp = eap_psk_process_3(data, ret, reqData, len, - respDataLen); - 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/contrib/wpa_supplicant/eap_psk_common.c b/contrib/wpa_supplicant/eap_psk_common.c deleted file mode 100644 index 8d896ae639d5..000000000000 --- a/contrib/wpa_supplicant/eap_psk_common.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * EAP server/peer: EAP-PSK shared routines - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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_wrap.h" -#include "eap_defs.h" -#include "eap_psk_common.h" - -#define aes_block_size 16 - - -void eap_psk_key_setup(const u8 *psk, u8 *ak, u8 *kdk) -{ - os_memset(ak, 0, aes_block_size); - aes_128_encrypt_block(psk, ak, ak); - os_memcpy(kdk, ak, aes_block_size); - ak[aes_block_size - 1] ^= 0x01; - kdk[aes_block_size - 1] ^= 0x02; - aes_128_encrypt_block(psk, ak, ak); - aes_128_encrypt_block(psk, kdk, kdk); -} - - -void 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; - - aes_128_encrypt_block(kdk, rand_p, hash); - - hash[aes_block_size - 1] ^= counter; - aes_128_encrypt_block(kdk, hash, tek); - hash[aes_block_size - 1] ^= counter; - counter++; - - for (i = 0; i < EAP_MSK_LEN / aes_block_size; i++) { - hash[aes_block_size - 1] ^= counter; - aes_128_encrypt_block(kdk, hash, &msk[i * aes_block_size]); - hash[aes_block_size - 1] ^= counter; - counter++; - } - - for (i = 0; i < EAP_EMSK_LEN / aes_block_size; i++) { - hash[aes_block_size - 1] ^= counter; - aes_128_encrypt_block(kdk, hash, &emsk[i * aes_block_size]); - hash[aes_block_size - 1] ^= counter; - counter++; - } -} diff --git a/contrib/wpa_supplicant/eap_psk_common.h b/contrib/wpa_supplicant/eap_psk_common.h deleted file mode 100644 index e1bdccf5916a..000000000000 --- a/contrib/wpa_supplicant/eap_psk_common.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * EAP server/peer: EAP-PSK shared routines - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 */ - -/* Shared prefix for all EAP-PSK frames */ -struct eap_psk_hdr { - u8 code; - u8 identifier; - u16 length; /* including code, identifier, and length */ - u8 type; /* EAP_TYPE_PSK */ - u8 flags; -} STRUCT_PACKED; - -/* EAP-PSK First Message (AS -> Supplicant) */ -struct eap_psk_hdr_1 { - u8 code; - u8 identifier; - u16 length; /* including code, identifier, and length */ - u8 type; /* EAP_TYPE_PSK */ - 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 code; - u8 identifier; - u16 length; /* including code, identifier, and length */ - u8 type; /* EAP_TYPE_PSK */ - 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 code; - u8 identifier; - u16 length; /* including code, identifier, and length */ - u8 type; /* EAP_TYPE_PSK */ - 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 code; - u8 identifier; - u16 length; /* including code, identifier, and length */ - u8 type; /* EAP_TYPE_PSK */ - 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 */ - - -void eap_psk_key_setup(const u8 *psk, u8 *ak, u8 *kdk); -void 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/contrib/wpa_supplicant/eap_sake.c b/contrib/wpa_supplicant/eap_sake.c deleted file mode 100644 index 85ca4a41d88a..000000000000 --- a/contrib/wpa_supplicant/eap_sake.c +++ /dev/null @@ -1,515 +0,0 @@ -/* - * EAP peer method: EAP-SAKE (RFC 4763) - * Copyright (c) 2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "config_ssid.h" -#include "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 wpa_ssid *config = eap_get_config(sm); - struct eap_sake_data *data; - - if (config == NULL) { - wpa_printf(MSG_INFO, "EAP-SAKE: No configuration found"); - return NULL; - } - - if (!config->eappsk || - config->eappsk_len != 2 * EAP_SAKE_ROOT_SECRET_LEN) { - wpa_printf(MSG_INFO, "EAP-SAKE: No key (eappsk) of correct " - "length configured"); - return NULL; - } - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - data->state = IDENTITY; - - if (config->nai) { - data->peerid = os_malloc(config->nai_len); - if (data->peerid == NULL) { - eap_sake_deinit(sm, data); - return NULL; - } - os_memcpy(data->peerid, config->nai, config->nai_len); - data->peerid_len = config->nai_len; - } - - os_memcpy(data->root_secret_a, config->eappsk, - EAP_SAKE_ROOT_SECRET_LEN); - os_memcpy(data->root_secret_b, - config->eappsk + 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 u8 * eap_sake_build_msg(struct eap_sake_data *data, u8 **payload, - int id, size_t *length, u8 subtype) -{ - struct eap_sake_hdr *req; - u8 *msg; - - *length += sizeof(struct eap_sake_hdr); - - msg = os_zalloc(*length); - if (msg == NULL) { - wpa_printf(MSG_ERROR, "EAP-SAKE: Failed to allocate memory " - "request"); - return NULL; - } - - req = (struct eap_sake_hdr *) msg; - req->code = EAP_CODE_RESPONSE; - req->identifier = id; - req->length = htons((u16) *length); - req->type = EAP_TYPE_SAKE; - req->version = EAP_SAKE_VERSION; - req->session_id = data->session_id; - req->subtype = subtype; - *payload = (u8 *) (req + 1); - - return msg; -} - - -static u8 * eap_sake_process_identity(struct eap_sm *sm, - struct eap_sake_data *data, - struct eap_method_ret *ret, - const u8 *reqData, size_t reqDataLen, - const u8 *payload, size_t payload_len, - size_t *respDataLen) -{ - struct eap_sake_parse_attr attr; - u8 *resp, *rpos; - const struct eap_hdr *hdr = (const struct eap_hdr *) reqData; - - 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"); - - *respDataLen = 2 + data->peerid_len; - resp = eap_sake_build_msg(data, &rpos, hdr->identifier, respDataLen, - EAP_SAKE_SUBTYPE_IDENTITY); - if (resp == NULL) - return NULL; - - wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_PEERID"); - *rpos++ = EAP_SAKE_AT_PEERID; - *rpos++ = 2 + data->peerid_len; - if (data->peerid) - os_memcpy(rpos, data->peerid, data->peerid_len); - - eap_sake_state(data, CHALLENGE); - - return resp; -} - - -static u8 * eap_sake_process_challenge(struct eap_sm *sm, - struct eap_sake_data *data, - struct eap_method_ret *ret, - const u8 *reqData, size_t reqDataLen, - const u8 *payload, size_t payload_len, - size_t *respDataLen) -{ - struct eap_sake_parse_attr attr; - u8 *resp, *rpos; - const struct eap_hdr *hdr = (const struct eap_hdr *) reqData; - - 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 (hostapd_get_rand(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"); - - *respDataLen = 2 + EAP_SAKE_RAND_LEN + 2 + EAP_SAKE_MIC_LEN; - if (data->peerid) - *respDataLen += 2 + data->peerid_len; - resp = eap_sake_build_msg(data, &rpos, hdr->identifier, respDataLen, - EAP_SAKE_SUBTYPE_CHALLENGE); - if (resp == NULL) - return NULL; - - wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_RAND_P"); - *rpos++ = EAP_SAKE_AT_RAND_P; - *rpos++ = 2 + EAP_SAKE_RAND_LEN; - os_memcpy(rpos, data->rand_p, EAP_SAKE_RAND_LEN); - rpos += EAP_SAKE_RAND_LEN; - - if (data->peerid) { - wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_PEERID"); - *rpos++ = EAP_SAKE_AT_PEERID; - *rpos++ = 2 + data->peerid_len; - os_memcpy(rpos, data->peerid, data->peerid_len); - rpos += data->peerid_len; - } - - wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_MIC_P"); - *rpos++ = EAP_SAKE_AT_MIC_P; - *rpos++ = 2 + 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, - resp, *respDataLen, rpos, rpos)) { - wpa_printf(MSG_INFO, "EAP-SAKE: Failed to compute MIC"); - os_free(resp); - return NULL; - } - - eap_sake_state(data, CONFIRM); - - return resp; -} - - -static u8 * eap_sake_process_confirm(struct eap_sm *sm, - struct eap_sake_data *data, - struct eap_method_ret *ret, - const u8 *reqData, size_t reqDataLen, - const u8 *payload, size_t payload_len, - size_t *respDataLen) -{ - struct eap_sake_parse_attr attr; - u8 mic_s[EAP_SAKE_MIC_LEN]; - u8 *resp, *rpos; - const struct eap_hdr *hdr = (const struct eap_hdr *) reqData; - - 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, - reqData, reqDataLen, 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; - *respDataLen = 0; - wpa_printf(MSG_DEBUG, "EAP-SAKE: Sending " - "Response/Auth-Reject"); - return eap_sake_build_msg(data, &rpos, hdr->identifier, - respDataLen, - EAP_SAKE_SUBTYPE_AUTH_REJECT); - } - - wpa_printf(MSG_DEBUG, "EAP-SAKE: Sending Response/Confirm"); - - *respDataLen = 2 + EAP_SAKE_MIC_LEN; - resp = eap_sake_build_msg(data, &rpos, hdr->identifier, respDataLen, - EAP_SAKE_SUBTYPE_CONFIRM); - if (resp == NULL) - return NULL; - - wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_MIC_P"); - *rpos++ = EAP_SAKE_AT_MIC_P; - *rpos++ = 2 + 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, - resp, *respDataLen, rpos, rpos)) { - wpa_printf(MSG_INFO, "EAP-SAKE: Failed to compute MIC"); - os_free(resp); - return NULL; - } - - eap_sake_state(data, SUCCESS); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; - ret->allowNotifications = FALSE; - - return resp; -} - - -static u8 * eap_sake_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - struct eap_sake_data *data = priv; - const struct eap_sake_hdr *req; - u8 *resp; - const u8 *pos, *end; - size_t len; - u8 subtype, session_id; - - pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SAKE, - reqData, reqDataLen, &len); - if (pos == NULL || len < 3) { - ret->ignore = TRUE; - return NULL; - } - - req = (const struct eap_sake_hdr *) reqData; - subtype = req->subtype; - session_id = req->session_id; - pos = (const u8 *) (req + 1); - end = reqData + be_to_host16(req->length); - - 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, - reqDataLen, pos, end - pos, - respDataLen); - break; - case EAP_SAKE_SUBTYPE_CHALLENGE: - resp = eap_sake_process_challenge(sm, data, ret, reqData, - reqDataLen, pos, end - pos, - respDataLen); - break; - case EAP_SAKE_SUBTYPE_CONFIRM: - resp = eap_sake_process_confirm(sm, data, ret, reqData, - reqDataLen, pos, end - pos, - respDataLen); - 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/contrib/wpa_supplicant/eap_sake_common.c b/contrib/wpa_supplicant/eap_sake_common.c deleted file mode 100644 index 4b5476f101c8..000000000000 --- a/contrib/wpa_supplicant/eap_sake_common.c +++ /dev/null @@ -1,380 +0,0 @@ -/* - * EAP server/peer: EAP-SAKE shared routines - * Copyright (c) 2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "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; -} diff --git a/contrib/wpa_supplicant/eap_sake_common.h b/contrib/wpa_supplicant/eap_sake_common.h deleted file mode 100644 index ac6e8199d66b..000000000000 --- a/contrib/wpa_supplicant/eap_sake_common.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * EAP server/peer: EAP-SAKE shared routines - * Copyright (c) 2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 code; - u8 identifier; - u16 length; - u8 type; /* EAP_TYPE_SAKE */ - 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); - -#endif /* EAP_SAKE_COMMON_H */ diff --git a/contrib/wpa_supplicant/eap_sim.c b/contrib/wpa_supplicant/eap_sim.c deleted file mode 100644 index 53c198734980..000000000000 --- a/contrib/wpa_supplicant/eap_sim.c +++ /dev/null @@ -1,1003 +0,0 @@ -/* - * EAP peer method: EAP-SIM (RFC 4186) - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "config_ssid.h" -#include "crypto.h" -#include "pcsc_funcs.h" -#include "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, SUCCESS, FAILURE } state; -}; - - -static void * eap_sim_init(struct eap_sm *sm) -{ - struct eap_sim_data *data; - struct wpa_ssid *config = eap_get_config(sm); - - data = os_zalloc(sizeof(*data)); - if (data == NULL) - return NULL; - - if (hostapd_get_rand(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->state = 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) -{ - wpa_printf(MSG_DEBUG, "EAP-SIM: GSM authentication algorithm"); -#ifdef PCSC_FUNCS - 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; - } -#else /* PCSC_FUNCS */ - /* 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; - 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); - } - } - } -#endif /* PCSC_FUNCS */ - return 0; -} - - -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 u8 * eap_sim_client_error(struct eap_sim_data *data, - const struct eap_hdr *req, - size_t *respDataLen, int err) -{ - struct eap_sim_msg *msg; - - data->state = FAILURE; - data->num_id_req = 0; - data->num_notification = 0; - - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier, - 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, respDataLen, NULL, NULL, 0); -} - - -static u8 * eap_sim_response_start(struct eap_sm *sm, - struct eap_sim_data *data, - const struct eap_hdr *req, - size_t *respDataLen, - 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)", - req->identifier); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier, - 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, respDataLen, NULL, NULL, 0); -} - - -static u8 * eap_sim_response_challenge(struct eap_sim_data *data, - const struct eap_hdr *req, - size_t *respDataLen) -{ - struct eap_sim_msg *msg; - - wpa_printf(MSG_DEBUG, "Generating EAP-SIM Challenge (id=%d)", - req->identifier); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier, - EAP_TYPE_SIM, EAP_SIM_SUBTYPE_CHALLENGE); - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - return eap_sim_msg_finish(msg, respDataLen, data->k_aut, - (u8 *) data->sres, - data->num_chal * EAP_SIM_SRES_LEN); -} - - -static u8 * eap_sim_response_reauth(struct eap_sim_data *data, - const struct eap_hdr *req, - size_t *respDataLen, int counter_too_small) -{ - struct eap_sim_msg *msg; - unsigned int counter; - - wpa_printf(MSG_DEBUG, "Generating EAP-SIM Reauthentication (id=%d)", - req->identifier); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier, - 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; - } - wpa_printf(MSG_DEBUG, " AT_MAC"); - eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); - return eap_sim_msg_finish(msg, respDataLen, data->k_aut, data->nonce_s, - EAP_SIM_NONCE_S_LEN); -} - - -static u8 * eap_sim_response_notification(struct eap_sim_data *data, - const struct eap_hdr *req, - size_t *respDataLen, - 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)", - req->identifier); - msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier, - EAP_TYPE_SIM, EAP_SIM_SUBTYPE_NOTIFICATION); - wpa_printf(MSG_DEBUG, " AT_NOTIFICATION"); - eap_sim_msg_add(msg, EAP_SIM_AT_NOTIFICATION, notification, NULL, 0); - 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, respDataLen, k_aut, (u8 *) "", 0); -} - - -static u8 * eap_sim_process_start(struct eap_sm *sm, struct eap_sim_data *data, - const struct eap_hdr *req, - size_t *respDataLen, - 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, req, respDataLen, - 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, req, respDataLen, - 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, req, respDataLen, - 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, req, respDataLen, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - return eap_sim_response_start(sm, data, req, respDataLen, - attr->id_req); -} - - -static u8 * eap_sim_process_challenge(struct eap_sm *sm, - struct eap_sim_data *data, - const struct eap_hdr *req, - size_t reqDataLen, - size_t *respDataLen, - 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, req, respDataLen, - 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, req, respDataLen, - 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, req, respDataLen, - 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, req, respDataLen, - 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, req, respDataLen, - 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, (const u8 *) req, reqDataLen, - 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, req, respDataLen, - 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, req, respDataLen, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - eap_sim_learn_ids(data, &eattr); - os_free(decrypted); - } - - if (data->state != FAILURE) - data->state = 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, req, respDataLen); -} - - -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 eap_hdr *req, - size_t reqDataLen, - 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, (u8 *) req, reqDataLen, 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 u8 * eap_sim_process_notification(struct eap_sm *sm, - struct eap_sim_data *data, - const struct eap_hdr *req, - size_t reqDataLen, - size_t *respDataLen, - 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, req, respDataLen, - 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, req, respDataLen, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - if ((attr->notification & 0x4000) == 0 && - eap_sim_process_notification_auth(data, req, reqDataLen, attr)) { - return eap_sim_client_error(data, req, respDataLen, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - eap_sim_report_notification(sm->msg_ctx, attr->notification, 0); - if (attr->notification >= 0 && attr->notification < 32768) { - data->state = FAILURE; - } - return eap_sim_response_notification(data, req, respDataLen, - attr->notification); -} - - -static u8 * eap_sim_process_reauthentication(struct eap_sm *sm, - struct eap_sim_data *data, - const struct eap_hdr *req, - size_t reqDataLen, - size_t *respDataLen, - 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, req, respDataLen, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - } - - data->reauth = 1; - if (eap_sim_verify_mac(data->k_aut, (const u8 *) req, reqDataLen, - attr->mac, (u8 *) "", 0)) { - wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication " - "did not have valid AT_MAC"); - return eap_sim_client_error(data, req, respDataLen, - 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, req, respDataLen, - 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, req, respDataLen, - 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, req, respDataLen, - 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, req, respDataLen, 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->state != FAILURE) - data->state = 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, req, respDataLen, 0); -} - - -static u8 * eap_sim_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - struct eap_sim_data *data = priv; - const struct eap_hdr *req; - u8 subtype, *res; - const u8 *pos; - struct eap_sim_attrs attr; - size_t len; - - wpa_hexdump(MSG_DEBUG, "EAP-SIM: EAP data", reqData, reqDataLen); - 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, reqDataLen, &len); - if (pos == NULL || len < 1) { - ret->ignore = TRUE; - return NULL; - } - req = (const struct eap_hdr *) reqData; - 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, reqData + len, &attr, 0, 0)) { - res = eap_sim_client_error(data, req, respDataLen, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - goto done; - } - - switch (subtype) { - case EAP_SIM_SUBTYPE_START: - res = eap_sim_process_start(sm, data, req, - respDataLen, &attr); - break; - case EAP_SIM_SUBTYPE_CHALLENGE: - res = eap_sim_process_challenge(sm, data, req, len, - respDataLen, &attr); - break; - case EAP_SIM_SUBTYPE_NOTIFICATION: - res = eap_sim_process_notification(sm, data, req, len, - respDataLen, &attr); - break; - case EAP_SIM_SUBTYPE_REAUTHENTICATION: - res = eap_sim_process_reauthentication(sm, data, req, len, - respDataLen, &attr); - break; - case EAP_SIM_SUBTYPE_CLIENT_ERROR: - wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Client-Error"); - res = eap_sim_client_error(data, req, respDataLen, - EAP_SIM_UNABLE_TO_PROCESS_PACKET); - break; - default: - wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown subtype=%d", subtype); - res = eap_sim_client_error(data, req, respDataLen, - 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 = DECISION_COND_SUCC; - ret->methodState = METHOD_DONE; - } - - 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); -} - - -static void * eap_sim_init_for_reauth(struct eap_sm *sm, void *priv) -{ - struct eap_sim_data *data = priv; - if (hostapd_get_rand(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; - data->state = 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/contrib/wpa_supplicant/eap_sim_common.c b/contrib/wpa_supplicant/eap_sim_common.c deleted file mode 100644 index cc430239ab97..000000000000 --- a/contrib/wpa_supplicant/eap_sim_common.c +++ /dev/null @@ -1,849 +0,0 @@ -/* - * EAP peer: EAP-SIM/AKA shared routines - * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "sha1.h" -#include "crypto.h" -#include "aes_wrap.h" -#include "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 u8 *req, size_t req_len, - 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 || req_len < EAP_SIM_MAC_LEN || mac < req || - mac > req + req_len - EAP_SIM_MAC_LEN) - return -1; - - tmp = os_malloc(req_len); - if (tmp == NULL) - return -1; - - addr[0] = tmp; - len[0] = req_len; - addr[1] = extra; - len[1] = extra_len; - - /* HMAC-SHA1-128 */ - os_memcpy(tmp, req, req_len); - os_memset(tmp + (mac - req), 0, EAP_SIM_MAC_LEN); - wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Verify MAC - msg", tmp, req_len); - 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, 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); -} - - -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"); - attr->identity = apos + 2; - attr->identity_len = alen - 2; - 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"); - 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; - 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); - - aes_128_cbc_decrypt(k_encr, iv, decrypted, encr_data_len); - 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 { - u8 *buf; - size_t buf_len, used; - size_t mac, iv, encr; /* index from buf */ -}; - - -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->buf = os_zalloc(EAP_SIM_INIT_LEN); - if (msg->buf == NULL) { - os_free(msg); - return NULL; - } - msg->buf_len = EAP_SIM_INIT_LEN; - eap = (struct eap_hdr *) msg->buf; - eap->code = code; - eap->identifier = id; - msg->used = sizeof(*eap); - - pos = (u8 *) (eap + 1); - *pos++ = type; - *pos++ = subtype; - *pos++ = 0; /* Reserved */ - *pos++ = 0; /* Reserved */ - msg->used += 4; - - return msg; -} - - -u8 * eap_sim_msg_finish(struct eap_sim_msg *msg, size_t *len, const u8 *k_aut, - const u8 *extra, size_t extra_len) -{ - struct eap_hdr *eap; - u8 *buf; - - if (msg == NULL) - return NULL; - - eap = (struct eap_hdr *) msg->buf; - eap->length = host_to_be16(msg->used); - - if (k_aut && msg->mac) { - eap_sim_add_mac(k_aut, msg->buf, msg->used, - msg->buf + msg->mac, extra, extra_len); - } - - *len = msg->used; - buf = msg->buf; - os_free(msg); - return buf; -} - - -void eap_sim_msg_free(struct eap_sim_msg *msg) -{ - if (msg) { - os_free(msg->buf); - os_free(msg); - } -} - - -static int eap_sim_msg_resize(struct eap_sim_msg *msg, size_t add_len) -{ - if (msg->used + add_len > msg->buf_len) { - u8 *nbuf = os_realloc(msg->buf, msg->used + add_len); - if (nbuf == NULL) - return -1; - msg->buf = nbuf; - msg->buf_len = msg->used + add_len; - } - return 0; -} - - -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, *pos; - - if (msg == NULL) - return NULL; - - pad_len = (4 - attr_len % 4) % 4; - attr_len += pad_len; - if (eap_sim_msg_resize(msg, attr_len)) - return NULL; - start = pos = msg->buf + msg->used; - *pos++ = attr; - *pos++ = attr_len / 4; - os_memcpy(pos, data, len); - if (pad_len) { - pos += len; - os_memset(pos, 0, pad_len); - } - msg->used += attr_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, *pos; - - if (msg == NULL) - return NULL; - - pad_len = (4 - attr_len % 4) % 4; - attr_len += pad_len; - if (eap_sim_msg_resize(msg, attr_len)) - return NULL; - start = pos = msg->buf + msg->used; - *pos++ = attr; - *pos++ = attr_len / 4; - WPA_PUT_BE16(pos, value); - pos += 2; - if (data) - os_memcpy(pos, data, len); - if (pad_len) { - pos += len; - os_memset(pos, 0, pad_len); - } - msg->used += attr_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 - 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 - msg->buf) + 4; - if (hostapd_get_rand(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 - 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 = msg->used - 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); - msg->buf[msg->encr + 1] = encr_len / 4 + 1; - aes_128_cbc_encrypt(k_encr, msg->buf + msg->iv, - msg->buf + msg->encr + 4, encr_len); - - return 0; -} - - -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/contrib/wpa_supplicant/eap_sim_common.h b/contrib/wpa_supplicant/eap_sim_common.h deleted file mode 100644 index 9c983a864e3e..000000000000 --- a/contrib/wpa_supplicant/eap_sim_common.h +++ /dev/null @@ -1,166 +0,0 @@ -/* - * EAP peer: EAP-SIM/AKA shared routines - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 - -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 u8 *req, size_t req_len, - const u8 *mac, const u8 *extra, size_t extra_len); -void eap_sim_add_mac(const u8 *k_aut, u8 *msg, size_t msg_len, u8 *mac, - const u8 *extra, size_t extra_len); - - -/* 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_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 - -/* 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 - - -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; - size_t num_chal, version_list_len, encr_data_len; - size_t next_pseudonym_len, next_reauth_id_len, identity_len, res_len; - enum eap_sim_id_req id_req; - int notification, counter, selected_version, client_error_code; - int counter_too_small; -}; - -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); -u8 * eap_sim_msg_finish(struct eap_sim_msg *msg, size_t *len, 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/contrib/wpa_supplicant/eap_testing.txt b/contrib/wpa_supplicant/eap_testing.txt deleted file mode 100644 index 18c5c3f936b2..000000000000 --- a/contrib/wpa_supplicant/eap_testing.txt +++ /dev/null @@ -1,359 +0,0 @@ -Automatic regression and interoperability testing of wpa_supplicant's -IEEE 802.1X/EAPOL authentication - -Test program: -- Linked some parts of IEEE 802.1X Authenticator implementation from - hostapd (RADIUS client and RADIUS processing, EAP<->RADIUS - encapsulation/decapsulation) into wpa_supplicant. -- Replaced wpa_supplicant.c and wpa.c with test code that trigger - IEEE 802.1X authentication automatically without need for wireless - client card or AP. -- For EAP methods that generate keying material, the key derived by the - Supplicant is verified to match with the one received by the (now - integrated) Authenticator. - -The full automated test suite can now be run in couple of seconds, but -I'm more than willing to add new RADIUS authentication servers to make -this take a bit more time.. ;-) As an extra bonus, this can also be -seen as automatic regression/interoperability testing for the RADIUS -server, too. - -In order for me to be able to use a new authentication server, the -server need to be available from Internet (at least from one static IP -address) and I will need to get suitable user name/password pairs, -certificates, and private keys for testing use. Other alternative -would be to get an evaluation version of the server so that I can -install it on my own test setup. If you are interested in providing -either server access or evaluation version, please contact me -(j@w1.fi). - - -Test matrix - -+) tested successfully -F) failed --) server did not support -?) not tested - -Cisco ACS ----------------------------------------------------------. -hostapd --------------------------------------------------------. | -Cisco Aironet 1200 AP (local RADIUS server) ----------------. | | -Periodik Labs Elektron ---------------------------------. | | | -Lucent NavisRadius ---------------------------------. | | | | -Interlink RAD-Series ---------------------------. | | | | | -Radiator -----------------------------------. | | | | | | -Meetinghouse Aegis ---------------------. | | | | | | | -Funk Steel-Belted ------------------. | | | | | | | | -Funk Odyssey -------------------. | | | | | | | | | -Microsoft IAS --------------. | | | | | | | | | | -FreeRADIUS -------------. | | | | | | | | | | | - | | | | | | | | | | | | - -EAP-MD5 + - - + + + + + - - + + -EAP-GTC + - - ? + + + + - - + - -EAP-OTP - - - - - + - - - - - - -EAP-MSCHAPv2 + - - + + + + + - - + - -EAP-TLS + + + + + + + + - - + + -EAP-PEAPv0/MSCHAPv2 + + + + + + + + + - + + -EAP-PEAPv0/GTC + - + - + + + + - - + + -EAP-PEAPv0/OTP - - - - - + - - - - - - -EAP-PEAPv0/MD5 + - - + + + + + - - + - -EAP-PEAPv0/TLS - + - + + + F + - - - - -EAP-PEAPv1/MSCHAPv2 - - + + + +1 + +5 +8 - + + -EAP-PEAPv1/GTC - - + + + +1 + +5 +8 - + + -EAP-PEAPv1/OTP - - - - - +1 - - - - - - -EAP-PEAPv1/MD5 - - - + + +1 + +5 - - + - -EAP-PEAPv1/TLS - - - + + +1 F +5 - - - - -EAP-TTLS/CHAP + - +2 + + + + + + - + - -EAP-TTLS/MSCHAP + - + + + + + + + - + - -EAP-TTLS/MSCHAPv2 + - + + + + + + + - + - -EAP-TTLS/PAP + - + + + + + + + - + - -EAP-TTLS/EAP-MD5 + - +2 + + + + + + - + - -EAP-TTLS/EAP-GTC + - +2 ? + + + + - - + - -EAP-TTLS/EAP-OTP - - - - - + - - - - - - -EAP-TTLS/EAP-MSCHAPv2 + - +2 + + + + + + - + - -EAP-TTLS/EAP-TLS - - +2 + F + + + - - - - -EAP-SIM +3 - - ? - + - ? - - + - -EAP-AKA - - - - - + - - - - + - -EAP-PSK +7 - - - - - - - - - + - -EAP-PAX - - - - - - - - - - + - -EAP-SAKE - - - - - - - - - - + - -EAP-GPSK - - - - - - - - - - + - -EAP-FAST - - - + - - - - - + - + -LEAP + - + + + + F +6 - + - + - -1) PEAPv1 required new label, "client PEAP encryption" instead of "client EAP - encryption", during key derivation (requires phase1="peaplabel=1" in the - network configuration in wpa_supplicant.conf) -2) used FreeRADIUS as inner auth server -3) required a patch to FreeRADIUS to fix EAP-SIM -5) PEAPv1 required termination of negotiation on tunneled EAP-Success and new - label in key deriviation - (phase1="peap_outer_success=0 peaplabel=1") (in "IETF Draft 5" mode) -6) Authenticator simulator required patching for handling Access-Accept within - negotiation (for the first EAP-Success of LEAP) -7) EAP-PSK is not included in FreeRADIUS distribution; used external - rlm_eap_psk implementation from - http://perso.rd.francetelecom.fr/bersani/EAP_PSK/ - EAP-PSKWindowsimplementations.html -8) PEAPv1 used non-standard version negotiation (client had to force v1 even - though server reported v0 as the highest supported version) - - -Automated tests: - -FreeRADIUS (1.0pre and CVS snapshot) -- EAP-MD5-Challenge -- EAP-GTC -- EAP-MSCHAPv2 -- EAP-TLS -- EAP-PEAPv0 / MSCHAPv2 -- EAP-PEAPv0 / GTC -- EAP-PEAPv0 / MD5-Challenge -- EAP-TTLS / EAP-MD5-Challenge -- EAP-TTLS / EAP-GTC -- EAP-TTLS / EAP-MSCHAPv2 -- EAP-TTLS / CHAP -- EAP-TTLS / PAP -- EAP-TTLS / MSCHAP -- EAP-TTLS / MSCHAPv2 -- EAP-SIM -* not supported in FreeRADIUS - - EAP-PEAP / TLS (Unable to tunnel TLS inside of TLS) - - EAP-TTLS / EAP-TLS (Unable to tunnel TLS inside of TLS) - -Microsoft Windows Server 2003 / IAS -- EAP-TLS -- EAP-PEAPv0 / MSCHAPv2 -- EAP-PEAPv0 / TLS -- EAP-MD5 -* IAS does not seem to support other EAP methods - -Funk Odyssey 2.01.00.653 -- EAP-TLS -- EAP-PEAPv0 / MSCHAPv2 -- EAP-PEAPv0 / GTC -- EAP-PEAPv1 / MSCHAPv2 -- EAP-PEAPv1 / GTC - Note: PEAPv1 requires TLS key derivation to use label "client EAP encryption" -- EAP-TTLS / CHAP (using FreeRADIUS as inner auth srv) -- EAP-TTLS / MSCHAP -- EAP-TTLS / MSCHAPv2 -- EAP-TTLS / PAP -- EAP-TTLS / EAP-MD5-Challenge (using FreeRADIUS as inner auth srv) -- EAP-TTLS / EAP-GTC (using FreeRADIUS as inner auth srv) -- EAP-TTLS / EAP-MSCHAPv2 (using FreeRADIUS as inner auth srv) -- EAP-TTLS / EAP-TLS (using FreeRADIUS as inner auth srv) -* not supported in Odyssey: - - EAP-MD5-Challenge - - EAP-GTC - - EAP-MSCHAPv2 - - EAP-PEAP / MD5-Challenge - - EAP-PEAP / TLS - -Funk Steel-Belted Radius Enterprise Edition v4.71.739 -- EAP-MD5-Challenge -- EAP-MSCHAPv2 -- EAP-TLS -- EAP-PEAPv0 / MSCHAPv2 -- EAP-PEAPv0 / MD5 -- EAP-PEAPv0 / TLS -- EAP-PEAPv1 / MSCHAPv2 -- EAP-PEAPv1 / MD5 -- EAP-PEAPv1 / GTC -- EAP-PEAPv1 / TLS - Note: PEAPv1 requires TLS key derivation to use label "client EAP encryption" -- EAP-TTLS / CHAP -- EAP-TTLS / MSCHAP -- EAP-TTLS / MSCHAPv2 -- EAP-TTLS / PAP -- EAP-TTLS / EAP-MD5-Challenge -- EAP-TTLS / EAP-MSCHAPv2 -- EAP-TTLS / EAP-TLS - -Meetinghouse Aegis 1.1.4 -- EAP-MD5-Challenge -- EAP-GTC -- EAP-MSCHAPv2 -- EAP-TLS -- EAP-PEAPv0 / MSCHAPv2 -- EAP-PEAPv0 / TLS -- EAP-PEAPv0 / GTC -- EAP-PEAPv0 / MD5-Challenge -- EAP-PEAPv1 / MSCHAPv2 -- EAP-PEAPv1 / TLS -- EAP-PEAPv1 / GTC -- EAP-PEAPv1 / MD5-Challenge - Note: PEAPv1 requires TLS key derivation to use label "client EAP encryption" -- EAP-TTLS / CHAP -- EAP-TTLS / MSCHAP -- EAP-TTLS / MSCHAPv2 -- EAP-TTLS / PAP -- EAP-TTLS / EAP-MD5-Challenge -- EAP-TTLS / EAP-GTC -- EAP-TTLS / EAP-MSCHAPv2 -* did not work - - EAP-TTLS / EAP-TLS - (Server rejects authentication without any reason in debug log. It - looks like the inner TLS negotiation starts properly and the last - packet from Supplicant looks like the one sent in the Phase 1. The - server generates a valid looking reply in the same way as in Phase - 1, but then ends up sending Access-Reject. Maybe an issue with TTLS - fragmentation in the Aegis server(?) The packet seems to include - 1328 bytes of EAP-Message and this may go beyond the fragmentation - limit with AVP encapsulation and TLS tunneling. Note: EAP-PEAP/TLS - did work, so this issue seems to be with something TTLS specific.) - -Radiator 3.9 (eval, with all patches up to and including 2004-08-30) -- EAP-MD5-Challenge -- EAP-GTC -- EAP-OTP -- EAP-MSCHAPv2 -- EAP-TLS -- EAP-PEAPv0 / MSCHAPv2 -- EAP-PEAPv0 / GTC -- EAP-PEAPv0 / OTP -- EAP-PEAPv0 / MD5-Challenge -- EAP-PEAPv0 / TLS - Note: Needed to use unknown identity in outer auth and some times the server - seems to get confused and fails to send proper Phase 2 data. -- EAP-PEAPv1 / MSCHAPv2 -- EAP-PEAPv1 / GTC -- EAP-PEAPv1 / OTP -- EAP-PEAPv1 / MD5-Challenge -- EAP-PEAPv1 / TLS - Note: This has some additional requirements for EAPTLS_MaxFragmentSize. - Using 1300 for outer auth and 500 for inner auth seemed to work. - Note: Needed to use unknown identity in outer auth and some times the server - seems to get confused and fails to send proper Phase 2 data. -- EAP-TTLS / CHAP -- EAP-TTLS / MSCHAP -- EAP-TTLS / MSCHAPv2 -- EAP-TTLS / PAP -- EAP-TTLS / EAP-MD5-Challenge -- EAP-TTLS / EAP-GTC -- EAP-TTLS / EAP-OTP -- EAP-TTLS / EAP-MSCHAPv2 -- EAP-TTLS / EAP-TLS - Note: This has some additional requirements for EAPTLS_MaxFragmentSize. - Using 1300 for outer auth and 500 for inner auth seemed to work. -- EAP-SIM -- EAP-AKA - -Interlink Networks RAD-Series 6.1.2.7 -- EAP-MD5-Challenge -- EAP-GTC -- EAP-MSCHAPv2 -- EAP-TLS -- EAP-PEAPv0 / MSCHAPv2 -- EAP-PEAPv0 / GTC -- EAP-PEAPv0 / MD5-Challenge -- EAP-PEAPv1 / MSCHAPv2 -- EAP-PEAPv1 / GTC -- EAP-PEAPv1 / MD5-Challenge - Note: PEAPv1 requires TLS key derivation to use label "client EAP encryption" -- EAP-TTLS / CHAP -- EAP-TTLS / MSCHAP -- EAP-TTLS / MSCHAPv2 -- EAP-TTLS / PAP -- EAP-TTLS / EAP-MD5-Challenge -- EAP-TTLS / EAP-GTC -- EAP-TTLS / EAP-MSCHAPv2 -- EAP-TTLS / EAP-TLS -* did not work - - EAP-PEAPv0 / TLS - - EAP-PEAPv1 / TLS - (Failed to decrypt Phase 2 data) - -Lucent NavisRadius 4.4.0 -- EAP-MD5-Challenge -- EAP-GTC -- EAP-MSCHAPv2 -- EAP-TLS -- EAP-PEAPv0 / MD5-Challenge -- EAP-PEAPv0 / MSCHAPv2 -- EAP-PEAPv0 / GTC -- EAP-PEAPv0 / TLS -- EAP-PEAPv1 / MD5-Challenge -- EAP-PEAPv1 / MSCHAPv2 -- EAP-PEAPv1 / GTC -- EAP-PEAPv1 / TLS - "IETF Draft 5" mode requires phase1="peap_outer_success=0 peaplabel=1" - 'Cisco ACU 5.05' mode works without phase1 configuration -- EAP-TTLS / CHAP -- EAP-TTLS / MSCHAP -- EAP-TTLS / MSCHAPv2 -- EAP-TTLS / PAP -- EAP-TTLS / EAP-MD5-Challenge -- EAP-TTLS / EAP-MSCHAPv2 -- EAP-TTLS / EAP-GTC -- EAP-TTLS / EAP-TLS - -Note: user certificate from NavisRadius had private key in a format -that wpa_supplicant could not use. Converting this to PKCS#12 and then -back to PEM allowed wpa_supplicant to use the key. - - -hostapd v0.3.3 -- EAP-MD5-Challenge -- EAP-GTC -- EAP-MSCHAPv2 -- EAP-TLS -- EAP-PEAPv0 / MSCHAPv2 -- EAP-PEAPv0 / GTC -- EAP-PEAPv0 / MD5-Challenge -- EAP-PEAPv1 / MSCHAPv2 -- EAP-PEAPv1 / GTC -- EAP-PEAPv1 / MD5-Challenge -- EAP-TTLS / CHAP -- EAP-TTLS / MSCHAP -- EAP-TTLS / MSCHAPv2 -- EAP-TTLS / PAP -- EAP-TTLS / EAP-MD5-Challenge -- EAP-TTLS / EAP-GTC -- EAP-TTLS / EAP-MSCHAPv2 -- EAP-SIM -- EAP-PAX - -Cisco Secure ACS 3.3(1) for Windows Server -- PEAPv1/GTC worked, but PEAPv0/GTC failed in the end after password was - sent successfully; ACS is replying with empty PEAP packet (TLS ACK); - wpa_supplicant tries to decrypt this.. Replying with TLS ACK and and - marking the connection completed was enough to make this work. - - -PEAPv1: - -Funk Odyssey 2.01.00.653: -- uses tunneled EAP-Success, expects reply in tunnel or TLS ACK, sends MPPE - keys with outer EAP-Success message after this -- uses label "client EAP encryption" -- (peap_outer_success 1 and 2 work) - -Funk Steel-Belted Radius Enterprise Edition v4.71.739 -- uses tunneled EAP-Success, expects reply in tunnel or TLS ACK, sends MPPE - keys with outer EAP-Success message after this -- uses label "client EAP encryption" -- (peap_outer_success 1 and 2 work) - -Radiator 3.9: -- uses TLV Success and Reply, sends MPPE keys with outer EAP-Success message - after this -- uses label "client PEAP encryption" - -Lucent NavisRadius 4.4.0 (in "IETF Draft 5" mode): -- sends tunneled EAP-Success with MPPE keys and expects the authentication to - terminate at this point (gets somewhat confused with reply to this) -- uses label "client PEAP encryption" -- phase1="peap_outer_success=0 peaplabel=1" - -Lucent NavisRadius 4.4.0 (in "Cisco ACU 5.05" mode): -- sends tunneled EAP-Success with MPPE keys and expects to receive TLS ACK - as a reply -- uses label "client EAP encryption" - -Meetinghouse Aegis 1.1.4 -- uses tunneled EAP-Success, expects reply in tunnel or TLS ACK, sends MPPE - keys with outer EAP-Success message after this -- uses label "client EAP encryption" -- peap_outer_success 1 and 2 work diff --git a/contrib/wpa_supplicant/eap_tls.c b/contrib/wpa_supplicant/eap_tls.c deleted file mode 100644 index 03fcd89aed56..000000000000 --- a/contrib/wpa_supplicant/eap_tls.c +++ /dev/null @@ -1,289 +0,0 @@ -/* - * EAP peer method: EAP-TLS (RFC 2716) - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "config_ssid.h" -#include "tls.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 wpa_ssid *config = eap_get_config(sm); - if (config == NULL || - ((sm->init_phase2 ? config->private_key2 : config->private_key) - == NULL && 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_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_tls_ssl_deinit(sm, &data->ssl); - os_free(data->key_data); - os_free(data); -} - - -static u8 * eap_tls_failure(struct eap_sm *sm, struct eap_tls_data *data, - struct eap_method_ret *ret, int res, u8 *resp, - u8 id, size_t *respDataLen) -{ - wpa_printf(MSG_DEBUG, "EAP-TLS: TLS processing failed"); - - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - - if (res == -1) { - struct wpa_ssid *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_tls_build_ack(&data->ssl, respDataLen, 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_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 u8 * eap_tls_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - const struct eap_hdr *req; - size_t left; - int res; - u8 flags, *resp, id; - const u8 *pos; - struct eap_tls_data *data = priv; - - pos = eap_tls_process_init(sm, &data->ssl, EAP_TYPE_TLS, ret, - reqData, reqDataLen, &left, &flags); - if (pos == NULL) - return NULL; - req = (const struct eap_hdr *) reqData; - id = req->identifier; - - 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_tls_process_helper(sm, &data->ssl, EAP_TYPE_TLS, 0, id, pos, - left, &resp, respDataLen); - - if (res < 0) { - return eap_tls_failure(sm, data, ret, res, resp, id, - respDataLen); - } - - if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) - eap_tls_success(sm, data, ret); - - if (res == 1) { - return eap_tls_build_ack(&data->ssl, respDataLen, 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_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_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/contrib/wpa_supplicant/eap_tls_common.c b/contrib/wpa_supplicant/eap_tls_common.c deleted file mode 100644 index 95ae0622d4eb..000000000000 --- a/contrib/wpa_supplicant/eap_tls_common.c +++ /dev/null @@ -1,681 +0,0 @@ -/* - * EAP peer: EAP-TLS/PEAP/TTLS/FAST common functions - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "config_ssid.h" -#include "md5.h" -#include "sha1.h" -#include "tls.h" -#include "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_from_conf1(struct tls_connection_params *params, - struct wpa_ssid *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_id = config->engine_id; - params->pin = config->pin; - params->key_id = config->key_id; -} - - -static void eap_tls_params_from_conf2(struct tls_connection_params *params, - struct wpa_ssid *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; -} - - -static int eap_tls_params_from_conf(struct eap_sm *sm, - struct eap_ssl_data *data, - struct tls_connection_params *params, - struct wpa_ssid *config, int phase2) -{ - os_memset(params, 0, sizeof(*params)); - params->engine = config->engine; - if (phase2) - eap_tls_params_from_conf2(params, config); - else - eap_tls_params_from_conf1(params, config); - params->tls_ia = data->tls_ia; - - - 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 wpa_ssid *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 don't 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; - return -1; - } else if (res) { - wpa_printf(MSG_INFO, "TLS: Failed to set TLS connection " - "parameters"); - return -1; - } - - return 0; -} - - -/** - * eap_tls_ssl_init - Initialize shared TLS functionality - * @sm: Pointer to EAP state machine allocated with eap_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_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data, - struct wpa_ssid *config) -{ - int ret = -1; - 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) - goto done; - - if (eap_tls_init_connection(sm, data, config, ¶ms) < 0) - goto done; - - 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; - } - - ret = 0; - -done: - return ret; -} - - -/** - * eap_tls_ssl_deinit - Deinitialize shared TLS functionality - * @sm: Pointer to EAP state machine allocated with eap_sm_init() - * @data: Data for TLS processing - * - * This function deinitializes shared TLS functionality that was initialized - * with eap_tls_ssl_init(). - */ -void eap_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data) -{ - tls_connection_deinit(sm->ssl_ctx, data->conn); - os_free(data->tls_in); - os_free(data->tls_out); -} - - -/** - * eap_tls_derive_key - Derive a key based on TLS session data - * @sm: Pointer to EAP state machine allocated with eap_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_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_tls_data_reassemble - Reassemble TLS data - * @sm: Pointer to EAP state machine allocated with eap_sm_init() - * @data: Data for TLS processing - * @in_data: Next incoming TLS segment - * @in_len: Length of in_data - * @out_len: Variable for returning output data length - * @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. - */ -const u8 * eap_tls_data_reassemble( - struct eap_sm *sm, struct eap_ssl_data *data, const u8 *in_data, - size_t in_len, size_t *out_len, int *need_more_input) -{ - u8 *buf; - - *need_more_input = 0; - - if (data->tls_in_left > in_len || data->tls_in) { - if (data->tls_in_len + in_len == 0) { - os_free(data->tls_in); - data->tls_in = NULL; - data->tls_in_len = 0; - 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) data->tls_in_len, - (unsigned long) in_len); - return NULL; - } - if (data->tls_in_len + in_len > 65536) { - /* Limit length to avoid rogue servers from causing - * large memory allocations. */ - os_free(data->tls_in); - data->tls_in = NULL; - data->tls_in_len = 0; - wpa_printf(MSG_INFO, "SSL: Too long TLS fragment (size" - " over 64 kB)"); - return NULL; - } - buf = os_realloc(data->tls_in, data->tls_in_len + in_len); - if (buf == NULL) { - os_free(data->tls_in); - data->tls_in = NULL; - data->tls_in_len = 0; - wpa_printf(MSG_INFO, "SSL: Could not allocate memory " - "for TLS data"); - return NULL; - } - os_memcpy(buf + data->tls_in_len, in_data, in_len); - data->tls_in = buf; - data->tls_in_len += in_len; - if (in_len > data->tls_in_left) { - wpa_printf(MSG_INFO, "SSL: more data than TLS message " - "length indicated"); - data->tls_in_left = 0; - return NULL; - } - 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); - *need_more_input = 1; - return NULL; - } - } else { - data->tls_in_left = 0; - data->tls_in = os_malloc(in_len ? in_len : 1); - if (data->tls_in == NULL) - return NULL; - os_memcpy(data->tls_in, in_data, in_len); - data->tls_in_len = in_len; - } - - *out_len = data->tls_in_len; - return data->tls_in; -} - - -static int eap_tls_process_input(struct eap_sm *sm, struct eap_ssl_data *data, - const u8 *in_data, size_t in_len, - u8 **out_data, size_t *out_len) -{ - const u8 *msg; - size_t msg_len; - int need_more_input; - u8 *appl_data; - size_t appl_data_len; - - msg = eap_tls_data_reassemble(sm, data, in_data, in_len, - &msg_len, &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_helper - pending " - "tls_out data even though tls_out_len = 0"); - os_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, msg_len, - &data->tls_out_len, - &appl_data, &appl_data_len); - - /* Clear reassembled input data (if the buffer was needed). */ - data->tls_in_left = data->tls_in_total = data->tls_in_len = 0; - os_free(data->tls_in); - data->tls_in = NULL; - - if (appl_data && - tls_connection_established(sm->ssl_ctx, data->conn) && - !tls_connection_get_failed(sm->ssl_ctx, data->conn)) { - wpa_hexdump_key(MSG_MSGDUMP, "SSL: Application data", - appl_data, appl_data_len); - *out_data = appl_data; - *out_len = appl_data_len; - return 2; - } - - os_free(appl_data); - - return 0; -} - - -static int eap_tls_process_output(struct eap_ssl_data *data, EapType eap_type, - int peap_version, u8 id, int ret, - u8 **out_data, size_t *out_len) -{ - size_t len; - u8 *pos, *flags; - int more_fragments, length_included; - - wpa_printf(MSG_DEBUG, "SSL: %lu bytes left to be sent out (of total " - "%lu bytes)", - (unsigned long) data->tls_out_len - data->tls_out_pos, - (unsigned long) data->tls_out_len); - - len = data->tls_out_len - data->tls_out_pos; - 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 && - (data->tls_out_len > data->tls_out_limit || - data->include_tls_length); - - *out_data = (u8 *) - eap_msg_alloc(EAP_VENDOR_IETF, eap_type, out_len, - 1 + length_included * 4 + len, EAP_CODE_RESPONSE, - id, &pos); - if (*out_data == NULL) - return -1; - - flags = pos++; - *flags = peap_version; - if (more_fragments) - *flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS; - if (length_included) { - *flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED; - WPA_PUT_BE32(pos, data->tls_out_len); - pos += 4; - } - - os_memcpy(pos, &data->tls_out[data->tls_out_pos], len); - data->tls_out_pos += len; - - if (!more_fragments) { - data->tls_out_len = 0; - data->tls_out_pos = 0; - os_free(data->tls_out); - data->tls_out = NULL; - } - - return ret; -} - - -/** - * eap_tls_process_helper - Process TLS handshake message - * @sm: Pointer to EAP state machine allocated with eap_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 - * @out_len: Buffer for returning the length of the response message - * Returns: 0 on success, 1 if more input data is needed, 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 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. - */ -int eap_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, - u8 **out_data, size_t *out_len) -{ - int ret = 0; - - WPA_ASSERT(data->tls_out_len == 0 || in_len == 0); - *out_len = 0; - *out_data = NULL; - - if (data->tls_out_len == 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, out_len); - if (res) - return res; - } - - if (data->tls_out == NULL) { - data->tls_out_len = 0; - return -1; - } - - if (tls_connection_get_failed(sm->ssl_ctx, data->conn)) { - wpa_printf(MSG_DEBUG, "SSL: Failed - tls_out available to " - "report error"); - ret = -1; - /* TODO: clean pin if engine used? */ - } - - if (data->tls_out_len == 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"); - os_free(data->tls_out); - data->tls_out = NULL; - return 1; - } - - return eap_tls_process_output(data, eap_type, peap_version, id, ret, - out_data, out_len); -} - - -/** - * eap_tls_build_ack - Build a TLS ACK frames - * @data: Data for TLS processing - * @respDataLen: Buffer for returning the length of the response message - * @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 allocated ACK frames or %NULL on failure - */ -u8 * eap_tls_build_ack(struct eap_ssl_data *data, size_t *respDataLen, u8 id, - EapType eap_type, int peap_version) -{ - struct eap_hdr *resp; - u8 *pos; - - resp = eap_msg_alloc(EAP_VENDOR_IETF, eap_type, respDataLen, - 1, EAP_CODE_RESPONSE, id, &pos); - if (resp == NULL) - return NULL; - wpa_printf(MSG_DEBUG, "SSL: Building ACK"); - *pos = peap_version; /* Flags */ - return (u8 *) resp; -} - - -/** - * eap_tls_reauth_init - Re-initialize shared TLS for session resumption - * @sm: Pointer to EAP state machine allocated with eap_sm_init() - * @data: Data for TLS processing - * Returns: 0 on success, -1 on failure - */ -int eap_tls_reauth_init(struct eap_sm *sm, struct eap_ssl_data *data) -{ - os_free(data->tls_in); - data->tls_in = NULL; - data->tls_in_len = data->tls_in_left = data->tls_in_total = 0; - os_free(data->tls_out); - data->tls_out = NULL; - data->tls_out_len = data->tls_out_pos = 0; - - return tls_connection_shutdown(sm->ssl_ctx, data->conn); -} - - -/** - * eap_tls_status - Get TLS status - * @sm: Pointer to EAP state machine allocated with eap_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_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_tls_process_init - Initial validation and processing of EAP requests - * @sm: Pointer to EAP state machine allocated with eap_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) - * @reqDataLen: Length of the EAP request - * @len: Buffer for returning length of the remaining payload - * @flags: Buffer for returning TLS flags - * Returns: Buffer to payload after TLS flags and length or %NULL on failure - */ -const u8 * eap_tls_process_init(struct eap_sm *sm, struct eap_ssl_data *data, - EapType eap_type, struct eap_method_ret *ret, - const u8 *reqData, size_t reqDataLen, - 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, reqDataLen, - &left); - if (pos == NULL) { - ret->ignore = TRUE; - return NULL; - } - *flags = *pos++; - left--; - wpa_printf(MSG_DEBUG, "SSL: Received packet(len=%lu) - " - "Flags 0x%02x", (unsigned long) reqDataLen, *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; - os_free(data->tls_in); - data->tls_in = NULL; - data->tls_in_len = 0; - } - pos += 4; - left -= 4; - } - - ret->ignore = FALSE; - ret->methodState = METHOD_MAY_CONT; - ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; - - *len = (size_t) left; - return pos; -} diff --git a/contrib/wpa_supplicant/eap_tls_common.h b/contrib/wpa_supplicant/eap_tls_common.h deleted file mode 100644 index 59de922c0ecb..000000000000 --- a/contrib/wpa_supplicant/eap_tls_common.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * EAP peer: EAP-TLS/PEAP/TTLS/FAST common functions - * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 { - struct tls_connection *conn; - - u8 *tls_out; - size_t tls_out_len; - size_t tls_out_pos; - size_t tls_out_limit; - u8 *tls_in; - size_t tls_in_len; - size_t tls_in_left; - size_t tls_in_total; - - int phase2; - int include_tls_length; /* include TLS length field even if the TLS - * data is not fragmented */ - int tls_ia; /* Enable TLS/IA */ - - 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_PEAP_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_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data, - struct wpa_ssid *config); -void eap_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data); -u8 * eap_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, - const char *label, size_t len); -const u8 * eap_tls_data_reassemble( - struct eap_sm *sm, struct eap_ssl_data *data, const u8 *in_data, - size_t in_len, size_t *out_len, int *need_more_input); -int eap_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, - u8 **out_data, size_t *out_len); -u8 * eap_tls_build_ack(struct eap_ssl_data *data, size_t *respDataLen, u8 id, - EapType eap_type, int peap_version); -int eap_tls_reauth_init(struct eap_sm *sm, struct eap_ssl_data *data); -int eap_tls_status(struct eap_sm *sm, struct eap_ssl_data *data, char *buf, - size_t buflen, int verbose); -const u8 * eap_tls_process_init(struct eap_sm *sm, struct eap_ssl_data *data, - EapType eap_type, struct eap_method_ret *ret, - const u8 *reqData, size_t reqDataLen, - size_t *len, u8 *flags); - -#endif /* EAP_TLS_COMMON_H */ diff --git a/contrib/wpa_supplicant/eap_tlv.c b/contrib/wpa_supplicant/eap_tlv.c deleted file mode 100644 index e5f29b630301..000000000000 --- a/contrib/wpa_supplicant/eap_tlv.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * EAP peer method: EAP-TLV (draft-josefsson-pppext-eap-tls-eap-07.txt) - * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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_tlv.h" - - -/** - * eap_tlv_build_nak - Build EAP-TLV NAK message - * @id: EAP identifier for the header - * @nak_type: TLV type (EAP_TLV_*) - * @resp_len: Buffer for returning the response length - * 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. - */ -u8 * eap_tlv_build_nak(int id, u16 nak_type, size_t *resp_len) -{ - struct eap_hdr *hdr; - u8 *pos; - - hdr = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, resp_len, - 10, EAP_CODE_RESPONSE, id, &pos); - if (hdr == NULL) - return NULL; - - *pos++ = 0x80; /* Mandatory */ - *pos++ = EAP_TLV_NAK_TLV; - /* Length */ - *pos++ = 0; - *pos++ = 6; - /* Vendor-Id */ - *pos++ = 0; - *pos++ = 0; - *pos++ = 0; - *pos++ = 0; - /* NAK-Type */ - WPA_PUT_BE16(pos, nak_type); - - return (u8 *) hdr; -} - - -/** - * 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) - * @resp_len: Buffer for returning the response length - * 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. - */ -u8 * eap_tlv_build_result(int id, u16 status, size_t *resp_len) -{ - struct eap_hdr *hdr; - u8 *pos; - - hdr = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, resp_len, - 6, EAP_CODE_RESPONSE, id, &pos); - if (hdr == NULL) - return NULL; - - *pos++ = 0x80; /* Mandatory */ - *pos++ = EAP_TLV_RESULT_TLV; - /* Length */ - *pos++ = 0; - *pos++ = 2; - /* Status */ - WPA_PUT_BE16(pos, status); - - return (u8 *) hdr; -} - - -/** - * eap_tlv_process - Process a received EAP-TLV message and generate a response - * @sm: Pointer to EAP state machine allocated with eap_sm_init() - * @ret: Return values from EAP request validation and processing - * @hdr: 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. - * @resp_len: Buffer for returning the response length - * Returns: 0 on success, -1 on failure - */ -int eap_tlv_process(struct eap_sm *sm, struct eap_method_ret *ret, - const struct eap_hdr *hdr, u8 **resp, size_t *resp_len, - int force_failure) -{ - size_t left, tlv_len; - const u8 *pos; - const u8 *result_tlv = NULL; - size_t result_tlv_len = 0; - int tlv_type, mandatory; - - /* Parse TLVs */ - left = be_to_host16(hdr->length) - sizeof(struct eap_hdr) - 1; - pos = (const u8 *) (hdr + 1); - pos++; - 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; - 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(hdr->identifier, - tlv_type, resp_len); - 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 (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(hdr->identifier, resp_status, - resp_len); - } - - return 0; -} diff --git a/contrib/wpa_supplicant/eap_tlv.h b/contrib/wpa_supplicant/eap_tlv.h deleted file mode 100644 index 789eeaadb1b8..000000000000 --- a/contrib/wpa_supplicant/eap_tlv.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * EAP peer method: EAP-TLV (draft-josefsson-pppext-eap-tls-eap-07.txt) - * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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_H -#define EAP_TLV_H - -/* EAP-TLV TLVs (draft-josefsson-ppext-eap-tls-eap-07.txt) */ -#define EAP_TLV_RESULT_TLV 3 /* Acknowledged Result */ -#define EAP_TLV_NAK_TLV 4 -#define EAP_TLV_CRYPTO_BINDING_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 /* draft-cam-winget-eap-fast-01.txt */ -#define EAP_TLV_CRYPTO_BINDING_TLV_ 12 /* draft-cam-winget-eap-fast-01.txt */ - -#define EAP_TLV_RESULT_SUCCESS 1 -#define EAP_TLV_RESULT_FAILURE 2 - -#define EAP_TLV_TYPE_MANDATORY 0x8000 - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -struct eap_tlv_hdr { - u16 tlv_type; - u16 length; -} STRUCT_PACKED; - -struct eap_tlv_nak_tlv { - u16 tlv_type; - u16 length; - u32 vendor_id; - u16 nak_type; -} STRUCT_PACKED; - -struct eap_tlv_result_tlv { - u16 tlv_type; - u16 length; - u16 status; -} STRUCT_PACKED; - -struct eap_tlv_intermediate_result_tlv { - u16 tlv_type; - u16 length; - u16 status; -} STRUCT_PACKED; - -struct eap_tlv_crypto_binding__tlv { - u16 tlv_type; - u16 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 { - u16 tlv_type; - u16 length; - u16 pac_type; - u16 pac_len; - u16 result; -} 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 - - -u8 * eap_tlv_build_nak(int id, u16 nak_type, size_t *resp_len); -u8 * eap_tlv_build_result(int id, u16 status, size_t *resp_len); -int eap_tlv_process(struct eap_sm *sm, struct eap_method_ret *ret, - const struct eap_hdr *hdr, u8 **resp, size_t *resp_len, - int force_failure); - -#endif /* EAP_TLV_H */ diff --git a/contrib/wpa_supplicant/eap_ttls.c b/contrib/wpa_supplicant/eap_ttls.c deleted file mode 100644 index bdffed41740b..000000000000 --- a/contrib/wpa_supplicant/eap_ttls.c +++ /dev/null @@ -1,1758 +0,0 @@ -/* - * EAP peer method: EAP-TTLS (draft-ietf-pppext-eap-ttls-03.txt) - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "config_ssid.h" -#include "ms_funcs.h" -#include "sha1.h" -#include "crypto.h" -#include "tls.h" -#include "eap_ttls.h" - - -/* Maximum supported PEAP version - * 0 = draft-ietf-pppext-eap-ttls-03.txt / draft-funk-eap-ttls-v0-00.txt - * 1 = draft-funk-eap-ttls-v1-00.txt - */ -#define EAP_TTLS_VERSION 0 /* TTLSv1 implementation is not yet complete */ - - -#define MSCHAPV2_KEY_LEN 16 - - -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 { - 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[20]; - int auth_response_valid; - u8 ident; - int resuming; /* starting a resumed session */ - int reauth; /* reauthentication */ - u8 *key_data; - - u8 *pending_phase2_req; - size_t pending_phase2_req_len; -}; - - -static void * eap_ttls_init(struct eap_sm *sm) -{ - struct eap_ttls_data *data; - struct wpa_ssid *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 (config && config->phase1) { - 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); - } - } - - 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 (config && config->phase2) { - char *start, *pos, *buf; - struct eap_method_type *methods = NULL, *_methods; - u8 method; - size_t num_methods = 0; - start = buf = os_strdup(config->phase2); - if (buf == NULL) { - eap_ttls_deinit(sm, data); - return NULL; - } - while (start && *start != '\0') { - int vendor; - pos = os_strstr(start, "autheap="); - if (pos == NULL) - break; - if (start != pos && *(pos - 1) != ' ') { - start = pos + 8; - continue; - } - - start = pos + 8; - 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, "EAP-TTLS: " - "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); - eap_ttls_deinit(sm, data); - return NULL; - } - methods = _methods; - methods[num_methods - 1].vendor = - vendor; - methods[num_methods - 1].method = - method; - } - - start = pos; - } - os_free(buf); - data->phase2_eap_types = methods; - data->num_phase2_eap_types = num_methods; - } - if (data->phase2_eap_types == NULL) { - data->phase2_eap_types = eap_get_phase2_types( - config, &data->num_phase2_eap_types); - } - if (data->phase2_eap_types == NULL) { - wpa_printf(MSG_ERROR, "EAP-TTLS: No Phase2 EAP method " - "available"); - eap_ttls_deinit(sm, data); - return NULL; - } - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Phase2 EAP types", - (u8 *) data->phase2_eap_types, - data->num_phase2_eap_types * - sizeof(struct eap_method_type)); - data->phase2_eap_type.vendor = EAP_VENDOR_IETF; - data->phase2_eap_type.method = EAP_TYPE_NONE; - } - - 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; - } - - return data; -} - - -static void eap_ttls_deinit(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->deinit(sm, data->phase2_priv); - os_free(data->phase2_eap_types); - if (data->ssl_initialized) - eap_tls_ssl_deinit(sm, &data->ssl); - os_free(data->key_data); - os_free(data->pending_phase2_req); - os_free(data); -} - - -static int eap_ttls_encrypt(struct eap_sm *sm, struct eap_ttls_data *data, - int id, const u8 *plain, size_t plain_len, - u8 **out_data, size_t *out_len) -{ - int res; - u8 *pos; - struct eap_hdr *resp; - - /* TODO: add support for fragmentation, if needed. This will need to - * add TLS Message Length field, if the frame is fragmented. */ - resp = os_malloc(sizeof(struct eap_hdr) + 2 + data->ssl.tls_out_limit); - if (resp == NULL) - return -1; - - resp->code = EAP_CODE_RESPONSE; - resp->identifier = id; - - pos = (u8 *) (resp + 1); - *pos++ = EAP_TYPE_TTLS; - *pos++ = data->ttls_version; - - res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn, - plain, plain_len, - pos, data->ssl.tls_out_limit); - if (res < 0) { - wpa_printf(MSG_INFO, "EAP-TTLS: Failed to encrypt Phase 2 " - "data"); - os_free(resp); - return -1; - } - - *out_len = sizeof(struct eap_hdr) + 2 + res; - resp->length = host_to_be16(*out_len); - *out_data = (u8 *) resp; - return 0; -} - - -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 u8 * eap_ttls_avp_add(u8 *start, u8 *avphdr, u32 avp_code, - u32 vendor_id, int mandatory, - 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(u8 **resp, size_t *resp_len, u32 avp_code, - int mandatory) -{ - u8 *avp, *pos; - - avp = os_malloc(sizeof(struct ttls_avp) + *resp_len + 4); - if (avp == NULL) { - os_free(*resp); - *resp = NULL; - *resp_len = 0; - return -1; - } - - pos = eap_ttls_avp_hdr(avp, avp_code, 0, mandatory, *resp_len); - os_memcpy(pos, *resp, *resp_len); - pos += *resp_len; - AVP_PAD(avp, pos); - os_free(*resp); - *resp = avp; - *resp_len = pos - avp; - return 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; -} - - -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_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; -} - - -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; -} - - -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_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 int eap_ttls_phase2_nak(struct eap_ttls_data *data, struct eap_hdr *hdr, - u8 **resp, size_t *resp_len) -{ - struct eap_hdr *resp_hdr; - u8 *pos = (u8 *) (hdr + 1); - size_t i; - - /* TODO: add support for expanded Nak */ - wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 Request: Nak type=%d", *pos); - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Allowed Phase2 EAP types", - (u8 *) data->phase2_eap_types, data->num_phase2_eap_types * - sizeof(struct eap_method_type)); - *resp_len = sizeof(struct eap_hdr) + 1; - *resp = os_malloc(*resp_len + data->num_phase2_eap_types); - if (*resp == NULL) - return -1; - - resp_hdr = (struct eap_hdr *) (*resp); - resp_hdr->code = EAP_CODE_RESPONSE; - resp_hdr->identifier = hdr->identifier; - pos = (u8 *) (resp_hdr + 1); - *pos++ = EAP_TYPE_NAK; - 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 < 256) { - (*resp_len)++; - *pos++ = data->phase2_eap_types[i].method; - } - } - resp_hdr->length = host_to_be16(*resp_len); - - return 0; -} - - -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, - u8 **resp, size_t *resp_len) -{ - size_t len = be_to_host16(hdr->length); - u8 *pos; - struct eap_method_ret iret; - struct wpa_ssid *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, resp_len, 1); - break; - default: - if (data->phase2_eap_type.vendor == EAP_VENDOR_IETF && - data->phase2_eap_type.method == EAP_TYPE_NONE) { - 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 != *pos) - 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; - } - } - if (*pos != data->phase2_eap_type.method || - *pos == EAP_TYPE_NONE) { - if (eap_ttls_phase2_nak(data, hdr, resp, resp_len)) - return -1; - break; - } - - if (data->phase2_priv == NULL) { - data->phase2_method = eap_sm_get_eap_methods( - EAP_VENDOR_IETF, *pos); - if (data->phase2_method) { - sm->init_phase2 = 1; - sm->mschapv2_full_key = 1; - data->phase2_priv = - data->phase2_method->init(sm); - sm->init_phase2 = 0; - sm->mschapv2_full_key = 0; - } - } - if (data->phase2_priv == NULL || data->phase2_method == NULL) { - wpa_printf(MSG_INFO, "EAP-TTLS: failed to initialize " - "Phase 2 EAP method %d", *pos); - return -1; - } - os_memset(&iret, 0, sizeof(iret)); - *resp = data->phase2_method->process(sm, data->phase2_priv, - &iret, (u8 *) hdr, len, - resp_len); - 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; - } - 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); - } - } - } - 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(MSG_DEBUG, "EAP-TTLS: AVP encapsulate EAP Response", - *resp, *resp_len); - return eap_ttls_avp_encapsulate(resp, resp_len, - RADIUS_ATTR_EAP_MESSAGE, 1); -} - - -static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm, - struct eap_ttls_data *data, - struct eap_method_ret *ret, - u8 **resp, size_t *resp_len) -{ - struct wpa_ssid *config = eap_get_config(sm); - u8 *buf, *pos, *challenge, *username, *peer_challenge; - size_t username_len, i; - - wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 MSCHAPV2 Request"); - - /* MSCHAPv2 does not include optional domain name in the - * challenge-response calculation, so remove domain prefix - * (if present). */ - username = config->identity; - username_len = config->identity_len; - pos = username; - for (i = 0; i < username_len; i++) { - if (username[i] == '\\') { - username_len -= i + 1; - username += i + 1; - break; - } - } - - pos = buf = os_malloc(config->identity_len + 1000); - if (buf == NULL) { - wpa_printf(MSG_ERROR, - "EAP-TTLS/MSCHAPV2: Failed to allocate memory"); - return -1; - } - - /* User-Name */ - pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1, - config->identity, config->identity_len); - - /* MS-CHAP-Challenge */ - challenge = eap_ttls_implicit_challenge( - sm, data, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 1); - if (challenge == NULL) { - os_free(buf); - 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; - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAPV2: implicit auth_challenge", - challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAPV2: peer_challenge", - peer_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN); - wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: MSCHAPV2 username", - username, username_len); - wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: MSCHAPV2 password", - config->password, config->password_len); - generate_nt_response(challenge, peer_challenge, - username, username_len, - config->password, config->password_len, - pos); - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAPV2 response", pos, 24); - generate_authenticator_response(config->password, config->password_len, - peer_challenge, challenge, - username, username_len, - pos, data->auth_response); - data->auth_response_valid = 1; - - if (data->ttls_version > 0) { - u8 pw_hash[16], pw_hash_hash[16], master_key[16]; - u8 session_key[2 * MSCHAPV2_KEY_LEN]; - nt_password_hash(config->password, config->password_len, - pw_hash); - hash_nt_password_hash(pw_hash, pw_hash_hash); - get_master_key(pw_hash_hash, pos /* 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)); - } - - pos += 24; - os_free(challenge); - AVP_PAD(buf, pos); - - *resp = buf; - *resp_len = pos - buf; - - 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, - u8 **resp, size_t *resp_len) -{ - struct wpa_ssid *config = eap_get_config(sm); - u8 *buf, *pos, *challenge; - - wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 MSCHAP Request"); - - pos = buf = os_malloc(config->identity_len + 1000); - if (buf == NULL) { - wpa_printf(MSG_ERROR, - "EAP-TTLS/MSCHAP: Failed to allocate memory"); - return -1; - } - - /* User-Name */ - pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1, - config->identity, config->identity_len); - - /* MS-CHAP-Challenge */ - challenge = eap_ttls_implicit_challenge( - sm, data, EAP_TTLS_MSCHAP_CHALLENGE_LEN + 1); - if (challenge == NULL) { - os_free(buf); - 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; - nt_challenge_response(challenge, - config->password, config->password_len, - pos); /* NT-Response */ - wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: MSCHAP password", - config->password, config->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); - - *resp = buf; - *resp_len = pos - buf; - - 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, - u8 **resp, size_t *resp_len) -{ - struct wpa_ssid *config = eap_get_config(sm); - u8 *buf, *pos; - size_t pad; - - wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 PAP Request"); - - pos = buf = os_malloc(config->identity_len + config->password_len + - 100); - if (buf == NULL) { - wpa_printf(MSG_ERROR, - "EAP-TTLS/PAP: Failed to allocate memory"); - return -1; - } - - /* User-Name */ - pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1, - config->identity, config->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 = (16 - (config->password_len & 15)) & 15; - pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_USER_PASSWORD, 0, 1, - config->password_len + pad); - os_memcpy(pos, config->password, config->password_len); - pos += config->password_len; - os_memset(pos, 0, pad); - pos += pad; - AVP_PAD(buf, pos); - - *resp = buf; - *resp_len = pos - buf; - - 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, - u8 **resp, size_t *resp_len) -{ - struct wpa_ssid *config = eap_get_config(sm); - u8 *buf, *pos, *challenge; - const u8 *addr[3]; - size_t len[3]; - - wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 CHAP Request"); - - pos = buf = os_malloc(config->identity_len + 1000); - if (buf == NULL) { - wpa_printf(MSG_ERROR, - "EAP-TTLS/CHAP: Failed to allocate memory"); - return -1; - } - - /* User-Name */ - pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1, - config->identity, config->identity_len); - - /* CHAP-Challenge */ - challenge = eap_ttls_implicit_challenge( - sm, data, EAP_TTLS_CHAP_CHALLENGE_LEN + 1); - if (challenge == NULL) { - os_free(buf); - 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) */ - addr[0] = &data->ident; - len[0] = 1; - addr[1] = config->password; - len[1] = config->password_len; - addr[2] = challenge; - len[2] = EAP_TTLS_CHAP_CHALLENGE_LEN; - md5_vector(3, addr, len, pos); - - wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: CHAP username", - config->identity, config->identity_len); - wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: CHAP password", - config->password, config->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); - - *resp = buf; - *resp_len = pos - buf; - - 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, - const struct eap_hdr *req, - struct eap_hdr *hdr, - u8 **resp, size_t *resp_len) -{ - int res = 0; - size_t len; - - if (data->phase2_type == EAP_TTLS_PHASE2_MSCHAPV2 || - data->phase2_type == EAP_TTLS_PHASE2_MSCHAP || - data->phase2_type == EAP_TTLS_PHASE2_PAP || - data->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 (data->phase2_type) { - case EAP_TTLS_PHASE2_EAP: - res = eap_ttls_phase2_request_eap(sm, data, ret, hdr, - resp, resp_len); - break; - case EAP_TTLS_PHASE2_MSCHAPV2: - res = eap_ttls_phase2_request_mschapv2(sm, data, ret, - resp, resp_len); - break; - case EAP_TTLS_PHASE2_MSCHAP: - res = eap_ttls_phase2_request_mschap(sm, data, ret, - resp, resp_len); - break; - case EAP_TTLS_PHASE2_PAP: - res = eap_ttls_phase2_request_pap(sm, data, ret, - resp, resp_len); - break; - case EAP_TTLS_PHASE2_CHAP: - res = eap_ttls_phase2_request_chap(sm, data, ret, - resp, resp_len); - 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; -} - - -static u8 * eap_ttls_build_phase_finished(struct eap_sm *sm, - struct eap_ttls_data *data, - int id, int final, - size_t *reqDataLen) -{ - int len; - struct eap_hdr *req; - u8 *pos; - const int max_len = 300; - - len = sizeof(struct eap_hdr) + 2 + max_len; - req = os_malloc(len); - if (req == NULL) - return NULL; - - req->code = EAP_CODE_RESPONSE; - req->identifier = id; - - pos = (u8 *) (req + 1); - *pos++ = EAP_TYPE_TTLS; - *pos++ = data->ttls_version; - - len = tls_connection_ia_send_phase_finished(sm->ssl_ctx, - data->ssl.conn, - final, pos, max_len); - if (len < 0) { - os_free(req); - return NULL; - } - - *reqDataLen = sizeof(struct eap_hdr) + 2 + len; - req->length = host_to_be16(*reqDataLen); - - return (u8 *) req; -} - - -static int eap_ttls_decrypt(struct eap_sm *sm, struct eap_ttls_data *data, - struct eap_method_ret *ret, - const struct eap_hdr *req, - const u8 *in_data, size_t in_len, - u8 **out_data, size_t *out_len) -{ - u8 *in_decrypted = NULL, *pos; - int res, retval = 0; - struct eap_hdr *hdr = NULL; - u8 *resp = NULL, *mschapv2 = NULL, *eapdata = NULL; - size_t resp_len, eap_len = 0, len_decrypted = 0, len, buf_len, left; - struct ttls_avp *avp; - u8 recv_response[20]; - int mschapv2_error = 0; - struct wpa_ssid *config = eap_get_config(sm); - const u8 *msg; - size_t msg_len; - int need_more_input; - - wpa_printf(MSG_DEBUG, "EAP-TTLS: received %lu bytes encrypted data for" - " Phase 2", (unsigned long) in_len); - - 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. */ - os_free(data->ssl.tls_in); - data->ssl.tls_in = NULL; - data->ssl.tls_in_len = 0; - data->ssl.tls_in_left = 0; - data->ssl.tls_in_total = 0; - - in_decrypted = data->pending_phase2_req; - data->pending_phase2_req = NULL; - len_decrypted = data->pending_phase2_req_len; - if (data->pending_phase2_req_len == 0) { - os_free(in_decrypted); - in_decrypted = NULL; - goto fake_req_identity; - } - goto continue_req; - } - - if (in_len == 0 && data->phase2_start) { - 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_tls_build_ack(&data->ssl, out_len, - req->identifier, - EAP_TYPE_TTLS, 0); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; - data->phase2_success = 1; - return 0; - } - fake_req_identity: - wpa_printf(MSG_DEBUG, "EAP-TTLS: empty data in beginning of " - "Phase 2 - use fake EAP-Request Identity"); - buf_len = sizeof(*hdr) + 1; - in_decrypted = os_malloc(buf_len); - if (in_decrypted == NULL) { - wpa_printf(MSG_WARNING, "EAP-TTLS: failed to allocate " - "memory for fake EAP-Identity Request"); - retval = -1; - goto done; - } - hdr = (struct eap_hdr *) in_decrypted; - hdr->code = EAP_CODE_REQUEST; - hdr->identifier = 0; - hdr->length = host_to_be16(sizeof(*hdr) + 1); - in_decrypted[sizeof(*hdr)] = EAP_TYPE_IDENTITY; - goto process_eap; - } - - msg = eap_tls_data_reassemble(sm, &data->ssl, in_data, in_len, - &msg_len, &need_more_input); - if (msg == NULL) - return need_more_input ? 1 : -1; - - buf_len = in_len; - if (data->ssl.tls_in_total > buf_len) - buf_len = data->ssl.tls_in_total; - in_decrypted = os_malloc(buf_len); - if (in_decrypted == NULL) { - os_free(data->ssl.tls_in); - data->ssl.tls_in = NULL; - data->ssl.tls_in_len = 0; - wpa_printf(MSG_WARNING, "EAP-TTLS: failed to allocate memory " - "for decryption"); - retval = -1; - goto done; - } - - res = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn, - msg, msg_len, in_decrypted, buf_len); - os_free(data->ssl.tls_in); - data->ssl.tls_in = NULL; - data->ssl.tls_in_len = 0; - if (res < 0) { - wpa_printf(MSG_INFO, "EAP-TTLS: Failed to decrypt Phase 2 " - "data"); - retval = -1; - goto done; - } - len_decrypted = res; - - if (data->ttls_version > 0 && len_decrypted == 0 && - tls_connection_ia_final_phase_finished(sm->ssl_ctx, - data->ssl.conn)) { - 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, - req->identifier, 1, - out_len); - eap_ttls_v1_derive_key(sm, data); - goto done; - } - -continue_req: - data->phase2_start = 0; - - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Decrypted Phase 2 AVPs", - in_decrypted, len_decrypted); - if (len_decrypted < 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) len_decrypted, - (unsigned long) sizeof(struct ttls_avp)); - retval = -1; - goto done; - } - - /* Parse AVPs */ - pos = in_decrypted; - left = len_decrypted; - mschapv2 = NULL; - - 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 (avp_length > left) { - wpa_printf(MSG_WARNING, "EAP-TTLS: AVP overflow " - "(len=%d, left=%lu) - dropped", - (int) avp_length, (unsigned long) left); - retval = -1; - goto done; - } - if (avp_length < sizeof(*avp)) { - wpa_printf(MSG_WARNING, "EAP-TTLS: Invalid AVP length " - "%d", avp_length); - retval = -1; - goto done; - } - 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"); - retval = -1; - goto done; - } - vendor_id = be_to_host32(* (u32 *) 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 (eapdata == NULL) { - eapdata = os_malloc(dlen); - if (eapdata == NULL) { - retval = -1; - wpa_printf(MSG_WARNING, "EAP-TTLS: " - "failed to allocate memory " - "for Phase 2 EAP data"); - goto done; - } - os_memcpy(eapdata, dpos, dlen); - eap_len = dlen; - } else { - u8 *neweap = os_realloc(eapdata, - eap_len + dlen); - if (neweap == NULL) { - retval = -1; - wpa_printf(MSG_WARNING, "EAP-TTLS: " - "failed to allocate memory " - "for Phase 2 EAP data"); - goto done; - } - os_memcpy(neweap + eap_len, dpos, dlen); - eapdata = neweap; - eap_len += dlen; - } - } 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); - retval = -1; - break; - } - 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); - 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); - retval = -1; - goto done; - } 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; - if (left < avp_length + pad) - left = 0; - else - left -= avp_length + pad; - } - - switch (data->phase2_type) { - case EAP_TTLS_PHASE2_EAP: - if (eapdata == NULL) { - wpa_printf(MSG_WARNING, "EAP-TTLS: No EAP Message in " - "the packet - dropped"); - retval = -1; - goto done; - } - - wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Phase 2 EAP", - eapdata, eap_len); - hdr = (struct eap_hdr *) eapdata; - - if (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) eap_len, - (unsigned long) sizeof(*hdr)); - retval = -1; - goto done; - } - len = be_to_host16(hdr->length); - if (len > 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) eap_len); - retval = -1; - goto done; - } - wpa_printf(MSG_DEBUG, "EAP-TTLS: received Phase 2: code=%d " - "identifier=%d length=%lu", - hdr->code, hdr->identifier, (unsigned long) len); - process_eap: - switch (hdr->code) { - case EAP_CODE_REQUEST: - if (eap_ttls_phase2_request(sm, data, ret, req, hdr, - &resp, &resp_len)) { - wpa_printf(MSG_INFO, "EAP-TTLS: Phase2 " - "Request processing failed"); - retval = -1; - goto done; - } - break; - default: - wpa_printf(MSG_INFO, "EAP-TTLS: Unexpected code=%d in " - "Phase 2 EAP header", hdr->code); - retval = -1; - break; - } - break; - case EAP_TTLS_PHASE2_MSCHAPV2: - if (mschapv2_error) { - wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Received " - "MS-CHAP-Error - failed"); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - *out_data = eap_tls_build_ack(&data->ssl, out_len, - req->identifier, - EAP_TYPE_TTLS, 0); - break; - } - - if (mschapv2 == NULL) { - wpa_printf(MSG_WARNING, "EAP-TTLS: no MS-CHAP2-Success" - " AVP received for Phase2 MSCHAPV2"); - retval = -1; - break; - } - if (mschapv2[0] != data->ident) { - wpa_printf(MSG_WARNING, "EAP-TTLS: Ident mismatch " - "for Phase 2 MSCHAPV2 (received Ident " - "0x%02x, expected 0x%02x)", - mschapv2[0], data->ident); - retval = -1; - break; - } - if (!data->auth_response_valid || - mschapv2[1] != 'S' || mschapv2[2] != '=' || - hexstr2bin((char *) (mschapv2 + 3), recv_response, 20) || - os_memcmp(data->auth_response, recv_response, 20) != 0) { - wpa_printf(MSG_WARNING, "EAP-TTLS: Invalid " - "authenticator response in Phase 2 " - "MSCHAPV2 success request"); - retval = -1; - break; - } - - 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. */ - retval = 1; - goto done; - case EAP_TTLS_PHASE2_MSCHAP: - case EAP_TTLS_PHASE2_PAP: - case EAP_TTLS_PHASE2_CHAP: - /* 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"); - retval = -1; - break; - } - - if (resp) { - wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Encrypting Phase 2 data", - resp, resp_len); - - if (eap_ttls_encrypt(sm, data, req->identifier, - resp, resp_len, out_data, out_len)) { - wpa_printf(MSG_INFO, "EAP-TTLS: Failed to encrypt " - "a Phase 2 frame"); - } - os_free(resp); - } else if (config->pending_req_identity || - config->pending_req_password || - config->pending_req_otp || - config->pending_req_new_password) { - os_free(data->pending_phase2_req); - data->pending_phase2_req = os_malloc(len_decrypted); - if (data->pending_phase2_req) { - os_memcpy(data->pending_phase2_req, in_decrypted, - len_decrypted); - data->pending_phase2_req_len = len_decrypted; - } - } - -done: - os_free(in_decrypted); - os_free(eapdata); - - if (retval < 0) { - ret->methodState = METHOD_DONE; - ret->decision = DECISION_FAIL; - } - - return retval; -} - - -static u8 * eap_ttls_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - const struct eap_hdr *req; - size_t left; - int res; - u8 flags, *resp, id; - const u8 *pos; - struct eap_ttls_data *data = priv; - struct wpa_ssid *config = eap_get_config(sm); - - pos = eap_tls_process_init(sm, &data->ssl, EAP_TYPE_TTLS, ret, - reqData, reqDataLen, &left, &flags); - if (pos == NULL) - return NULL; - req = (const struct eap_hdr *) reqData; - id = req->identifier; - - if (flags & EAP_TLS_FLAGS_START) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Start (server ver=%d, own " - "ver=%d)", flags & EAP_PEAP_VERSION_MASK, - data->ttls_version); - if ((flags & EAP_PEAP_VERSION_MASK) < data->ttls_version) - data->ttls_version = flags & EAP_PEAP_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 NULL; - } - wpa_printf(MSG_DEBUG, "EAP-TTLS: Using TTLS version %d", - data->ttls_version); - - if (data->ttls_version > 0) - data->ssl.tls_ia = 1; - if (!data->ssl_initialized && - eap_tls_ssl_init(sm, &data->ssl, config)) { - wpa_printf(MSG_INFO, "EAP-TTLS: Failed to initialize " - "SSL."); - return NULL; - } - data->ssl_initialized = 1; - - wpa_printf(MSG_DEBUG, "EAP-TTLS: Start"); - /* draft-ietf-pppext-eap-ttls-03.txt, Ch. 8.1: - * EAP-TTLS Start packet may, in a future specification, be - * allowed to contain data. Client based on this draft version - * must ignore such data but must not reject the Start packet. - */ - 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) { - res = eap_ttls_decrypt(sm, data, ret, req, pos, left, - &resp, respDataLen); - } else { - res = eap_tls_process_helper(sm, &data->ssl, EAP_TYPE_TTLS, - data->ttls_version, id, pos, left, - &resp, respDataLen); - - 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 (*respDataLen == 0) { - if (eap_ttls_decrypt(sm, data, ret, req, NULL, - 0, &resp, respDataLen)) { - wpa_printf(MSG_WARNING, "EAP-TTLS: " - "failed to process early " - "start for Phase 2"); - } - res = 0; - } - data->resuming = 0; - } - - if (res == 2) { - /* - * Application data included in the handshake message. - */ - os_free(data->pending_phase2_req); - data->pending_phase2_req = resp; - data->pending_phase2_req_len = *respDataLen; - resp = NULL; - *respDataLen = 0; - res = eap_ttls_decrypt(sm, data, ret, req, pos, left, - &resp, respDataLen); - } - } - - 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; - } - } else if (data->ttls_version == 0 && sm->workaround && - ret->methodState == METHOD_MAY_CONT && - (ret->decision == DECISION_UNCOND_SUCC || - ret->decision == DECISION_COND_SUCC)) { - wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication " - "completed successfully (EAP workaround)"); - data->phase2_success = 1; - } - - if (res == 1) { - return eap_tls_build_ack(&data->ssl, respDataLen, 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; - os_free(data->pending_phase2_req); - data->pending_phase2_req = NULL; -} - - -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_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_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/contrib/wpa_supplicant/eap_ttls.h b/contrib/wpa_supplicant/eap_ttls.h deleted file mode 100644 index e0b2cbf45488..000000000000 --- a/contrib/wpa_supplicant/eap_ttls.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * EAP server/peer: EAP-TTLS (draft-ietf-pppext-eap-ttls-03.txt) - * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 { - u32 avp_code; - u32 avp_length; /* 8-bit flags, 24-bit length; - * length includes AVP header */ - /* optional 32-bit Vendor-ID */ - /* Data */ -}; - -struct ttls_avp_vendor { - u32 avp_code; - u32 avp_length; /* 8-bit flags, 24-bit length; - * length includes AVP header */ - u32 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/contrib/wpa_supplicant/eap_vendor_test.c b/contrib/wpa_supplicant/eap_vendor_test.c deleted file mode 100644 index 7db76be25f9d..000000000000 --- a/contrib/wpa_supplicant/eap_vendor_test.c +++ /dev/null @@ -1,198 +0,0 @@ -/* - * EAP peer method: Test method for vendor specific (expanded) EAP type - * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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" -#include "eloop.h" - - -#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 u8 * eap_vendor_test_process(struct eap_sm *sm, void *priv, - struct eap_method_ret *ret, - const u8 *reqData, size_t reqDataLen, - size_t *respDataLen) -{ - struct eap_vendor_test_data *data = priv; - const struct eap_hdr *req; - struct eap_hdr *resp; - const u8 *pos; - u8 *rpos; - size_t len; - - pos = eap_hdr_validate(EAP_VENDOR_ID, EAP_VENDOR_TYPE, - reqData, reqDataLen, &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; - req = (const struct eap_hdr *) reqData; - - wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Generating Response"); - ret->allowNotifications = TRUE; - - resp = eap_msg_alloc(EAP_VENDOR_ID, EAP_VENDOR_TYPE, respDataLen, 1, - EAP_CODE_RESPONSE, req->identifier, &rpos); - if (resp == NULL) - return NULL; - - if (data->state == INIT) { - *rpos = 2; - data->state = CONFIRM; - ret->methodState = METHOD_CONT; - ret->decision = DECISION_FAIL; - } else { - *rpos = 4; - data->state = SUCCESS; - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; - } - - return (u8 *) 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/contrib/wpa_supplicant/eapol_sm.c b/contrib/wpa_supplicant/eapol_sm.c deleted file mode 100644 index b76a75dc783e..000000000000 --- a/contrib/wpa_supplicant/eapol_sm.c +++ /dev/null @@ -1,1786 +0,0 @@ -/* - * WPA Supplicant / EAPOL state machines - * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "eapol_sm.h" -#include "eap.h" -#include "eloop.h" -#include "l2_packet.h" -#include "wpa.h" -#include "md5.h" -#include "rc4.h" -#include "state_machine.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 */ - - /* 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 wpa_ssid *config; - Boolean initial_req; - u8 *last_rx_key; - size_t last_rx_key_len; - u8 *eapReqData; /* for EAP */ - size_t eapReqDataLen; /* 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); - - -/* 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"); - } - - eloop_register_timeout(1, 0, eapol_port_timers_tick, eloop_ctx, sm); - eapol_sm_step(sm); -} - - -SM_STATE(SUPP_PAE, LOGOFF) -{ - SM_ENTRY(SUPP_PAE, LOGOFF); - eapol_sm_txLogoff(sm); - sm->logoffSent = TRUE; - sm->suppPortStatus = Unauthorized; -} - - -SM_STATE(SUPP_PAE, DISCONNECTED) -{ - SM_ENTRY(SUPP_PAE, DISCONNECTED); - sm->sPortMode = Auto; - sm->startCount = 0; - sm->logoffSent = FALSE; - sm->suppPortStatus = Unauthorized; - 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. - */ - sm->startWhen = 3; - } - 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; - sm->suppPortStatus = Unauthorized; - sm->cb_status = EAPOL_CB_FAILURE; -} - - -SM_STATE(SUPP_PAE, AUTHENTICATED) -{ - SM_ENTRY(SUPP_PAE, AUTHENTICATED); - sm->suppPortStatus = Authorized; - 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; - sm->sPortMode = ForceAuthorized; -} - - -SM_STATE(SUPP_PAE, S_FORCE_UNAUTH) -{ - SM_ENTRY(SUPP_PAE, S_FORCE_UNAUTH); - sm->suppPortStatus = Unauthorized; - 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; - 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); - 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(datakey, key_len, ekey, - IEEE8021X_KEY_IV_LEN + encr_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) -{ - u8 *resp; - size_t resp_len; - - wpa_printf(MSG_DEBUG, "EAPOL: txSuppRsp"); - resp = eap_get_eapRespData(sm->eap, &resp_len); - 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, resp, resp_len); - - /* eapRespData is not used anymore, so free it here */ - os_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; - os_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); -} - - -/** - * 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_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; -} - - -#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; - } - 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); - } - os_free(sm->eapReqData); - sm->eapReqDataLen = plen; - sm->eapReqData = os_malloc(sm->eapReqDataLen); - if (sm->eapReqData) { - wpa_printf(MSG_DEBUG, "EAPOL: Received EAP-Packet " - "frame"); - os_memcpy(sm->eapReqData, (u8 *) (hdr + 1), - sm->eapReqDataLen); - 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 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 wpa_ssid *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; - 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)) - return -1; - eap_key = eap_get_eapKeyData(sm->eap, &eap_len); - if (eap_key == NULL) - return -1; - if (len > eap_len) - return eap_len; - os_memcpy(key, eap_key, 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; - sm->SUPP_PAE_state = SUPP_PAE_AUTHENTICATED; - sm->suppPortStatus = Authorized; - eap_notify_success(sm->eap); -} - - -/** - * 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; - - /* Make sure we do not start sending EAPOL-Start frames first, but - * instead move to RESTART state to start EAPOL authentication. */ - sm->startWhen = 3; - - 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() - * - * 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) -{ - if (sm == NULL) - return; - eap_notify_lower_layer_success(sm->eap); -} - - -/** - * 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 wpa_ssid * eapol_sm_get_config(void *ctx) -{ - struct eapol_sm *sm = ctx; - return sm ? sm->config : NULL; -} - - -static u8 * eapol_sm_get_eapReqData(void *ctx, size_t *len) -{ - struct eapol_sm *sm = ctx; - if (sm == NULL || sm->eapReqData == NULL) { - *len = 0; - return NULL; - } - - *len = sm->eapReqDataLen; - 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; - break; - } -} - - -static void eapol_sm_set_config_blob(void *ctx, struct wpa_config_blob *blob) -{ - struct eapol_sm *sm = ctx; - if (sm && sm->ctx && sm->ctx->set_config_blob) - sm->ctx->set_config_blob(sm->ctx->ctx, blob); -} - - -static const struct wpa_config_blob * -eapol_sm_get_config_blob(void *ctx, const char *name) -{ - 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; -} - - -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); - } -} - - -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_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; - - sm->eap = eap_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); - - 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_sm_deinit(sm->eap); - os_free(sm->last_rx_key); - os_free(sm->eapReqData); - os_free(sm->ctx); - os_free(sm); -} diff --git a/contrib/wpa_supplicant/eapol_sm.h b/contrib/wpa_supplicant/eapol_sm.h deleted file mode 100644 index 927bfcb6595b..000000000000 --- a/contrib/wpa_supplicant/eapol_sm.h +++ /dev/null @@ -1,322 +0,0 @@ -/* - * WPA Supplicant / EAPOL state machines - * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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_SM_H -#define EAPOL_SM_H - -#include "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; -}; - - -struct wpa_ssid; - -#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 wpa_ssid *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); -void eapol_sm_invalidate_cached_session(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 wpa_ssid *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) -{ -} -static inline void eapol_sm_invalidate_cached_session(struct eapol_sm *sm) -{ -} -#endif /* IEEE8021X_EAPOL */ - -#endif /* EAPOL_SM_H */ diff --git a/contrib/wpa_supplicant/eapol_test.c b/contrib/wpa_supplicant/eapol_test.c deleted file mode 100644 index 52cba3615b17..000000000000 --- a/contrib/wpa_supplicant/eapol_test.c +++ /dev/null @@ -1,1088 +0,0 @@ -/* - * WPA Supplicant - test code - * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * IEEE 802.1X Supplicant test code (to be used in place of wpa_supplicant.c. - * Not used in production version. - */ - -#include "includes.h" -#include <assert.h> - -#include "common.h" -#include "config.h" -#include "eapol_sm.h" -#include "eap.h" -#include "eloop.h" -#include "wpa.h" -#include "eap_i.h" -#include "wpa_supplicant.h" -#include "wpa_supplicant_i.h" -#include "radius.h" -#include "radius_client.h" -#include "l2_packet.h" -#include "ctrl_iface.h" -#include "pcsc_funcs.h" - - -extern int wpa_debug_level; -extern int wpa_debug_show_keys; - -struct wpa_driver_ops *wpa_supplicant_drivers[] = { NULL }; - - -struct eapol_test_data { - struct wpa_supplicant *wpa_s; - - int eapol_test_num_reauths; - int no_mppe_keys; - int num_mppe_ok, num_mppe_mismatch; - - u8 radius_identifier; - struct radius_msg *last_recv_radius; - struct in_addr own_ip_addr; - struct radius_client_data *radius; - struct hostapd_radius_servers *radius_conf; - - u8 *last_eap_radius; /* last received EAP Response from Authentication - * Server */ - size_t last_eap_radius_len; - - u8 authenticator_pmk[PMK_LEN]; - size_t authenticator_pmk_len; - int radius_access_accept_received; - int radius_access_reject_received; - int auth_timed_out; - - u8 *eap_identity; - size_t eap_identity_len; - - char *connect_info; - u8 own_addr[ETH_ALEN]; -}; - -static struct eapol_test_data eapol_test; - - -static void send_eap_request_identity(void *eloop_ctx, void *timeout_ctx); - - -void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level, - char *fmt, ...) -{ - char *format; - int maxlen; - va_list ap; - - maxlen = os_strlen(fmt) + 100; - format = os_malloc(maxlen); - if (!format) - return; - - va_start(ap, fmt); - - - if (addr) - os_snprintf(format, maxlen, "STA " MACSTR ": %s", - MAC2STR(addr), fmt); - else - os_snprintf(format, maxlen, "%s", fmt); - - vprintf(format, ap); - printf("\n"); - - os_free(format); - - va_end(ap); -} - - -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_snprintf(buf, buflen, "%s", inet_ntoa(addr->u.v4)); - } 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) -{ - return 0; -} - - -static void ieee802_1x_encapsulate_radius(struct eapol_test_data *e, - const u8 *eap, size_t len) -{ - struct radius_msg *msg; - char buf[128]; - const struct eap_hdr *hdr; - const u8 *pos; - - wpa_printf(MSG_DEBUG, "Encapsulating EAP message into a RADIUS " - "packet"); - - e->radius_identifier = radius_client_get_id(e->radius); - msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST, - e->radius_identifier); - if (msg == NULL) { - printf("Could not create net RADIUS packet\n"); - return; - } - - radius_msg_make_authenticator(msg, (u8 *) e, sizeof(*e)); - - hdr = (const struct eap_hdr *) eap; - pos = (const u8 *) (hdr + 1); - if (len > sizeof(*hdr) && hdr->code == EAP_CODE_RESPONSE && - pos[0] == EAP_TYPE_IDENTITY) { - pos++; - os_free(e->eap_identity); - e->eap_identity_len = len - sizeof(*hdr) - 1; - e->eap_identity = os_malloc(e->eap_identity_len); - if (e->eap_identity) { - os_memcpy(e->eap_identity, pos, e->eap_identity_len); - wpa_hexdump(MSG_DEBUG, "Learned identity from " - "EAP-Response-Identity", - e->eap_identity, e->eap_identity_len); - } - } - - if (e->eap_identity && - !radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, - e->eap_identity, e->eap_identity_len)) { - printf("Could not add User-Name\n"); - goto fail; - } - - if (!radius_msg_add_attr(msg, RADIUS_ATTR_NAS_IP_ADDRESS, - (u8 *) &e->own_ip_addr, 4)) { - printf("Could not add NAS-IP-Address\n"); - goto fail; - } - - os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT, - MAC2STR(e->wpa_s->own_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; - } - - /* 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; - } - - os_snprintf(buf, sizeof(buf), "%s", e->connect_info); - 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 (e->last_recv_radius && e->last_recv_radius->hdr->code == - RADIUS_CODE_ACCESS_CHALLENGE) { - int res = radius_msg_copy_attr(msg, e->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"); - } - } - - radius_client_send(e->radius, msg, RADIUS_AUTH, e->wpa_s->own_addr); - return; - - fail: - radius_msg_free(msg); - os_free(msg); -} - - -static int eapol_test_eapol_send(void *ctx, int type, const u8 *buf, - size_t len) -{ - /* struct wpa_supplicant *wpa_s = ctx; */ - printf("WPA: eapol_test_eapol_send(type=%d len=%lu)\n", - type, (unsigned long) len); - if (type == IEEE802_1X_TYPE_EAP_PACKET) { - wpa_hexdump(MSG_DEBUG, "TX EAP -> RADIUS", buf, len); - ieee802_1x_encapsulate_radius(&eapol_test, buf, len); - } - return 0; -} - - -static void eapol_test_set_config_blob(void *ctx, - struct wpa_config_blob *blob) -{ - struct wpa_supplicant *wpa_s = ctx; - wpa_config_set_blob(wpa_s->conf, blob); -} - - -static const struct wpa_config_blob * -eapol_test_get_config_blob(void *ctx, const char *name) -{ - struct wpa_supplicant *wpa_s = ctx; - return wpa_config_get_blob(wpa_s->conf, name); -} - - -static void eapol_test_eapol_done_cb(void *ctx) -{ - printf("WPA: EAPOL processing complete\n"); -} - - -static void eapol_sm_reauth(void *eloop_ctx, void *timeout_ctx) -{ - struct eapol_test_data *e = eloop_ctx; - printf("\n\n\n\n\neapol_test: Triggering EAP reauthentication\n\n"); - e->radius_access_accept_received = 0; - send_eap_request_identity(e->wpa_s, NULL); -} - - -static int eapol_test_compare_pmk(struct eapol_test_data *e) -{ - u8 pmk[PMK_LEN]; - int ret = 1; - - if (eapol_sm_get_key(e->wpa_s->eapol, pmk, PMK_LEN) == 0) { - wpa_hexdump(MSG_DEBUG, "PMK from EAPOL", pmk, PMK_LEN); - if (os_memcmp(pmk, e->authenticator_pmk, PMK_LEN) != 0) { - printf("WARNING: PMK mismatch\n"); - wpa_hexdump(MSG_DEBUG, "PMK from AS", - e->authenticator_pmk, PMK_LEN); - } else if (e->radius_access_accept_received) - ret = 0; - } else if (e->authenticator_pmk_len == 16 && - eapol_sm_get_key(e->wpa_s->eapol, pmk, 16) == 0) { - wpa_hexdump(MSG_DEBUG, "LEAP PMK from EAPOL", pmk, 16); - if (os_memcmp(pmk, e->authenticator_pmk, 16) != 0) { - printf("WARNING: PMK mismatch\n"); - wpa_hexdump(MSG_DEBUG, "PMK from AS", - e->authenticator_pmk, 16); - } else if (e->radius_access_accept_received) - ret = 0; - } else if (e->radius_access_accept_received && e->no_mppe_keys) { - /* No keying material expected */ - ret = 0; - } - - if (ret && !e->no_mppe_keys) - e->num_mppe_mismatch++; - else if (!e->no_mppe_keys) - e->num_mppe_ok++; - - return ret; -} - - -static void eapol_sm_cb(struct eapol_sm *eapol, int success, void *ctx) -{ - struct eapol_test_data *e = ctx; - printf("eapol_sm_cb: success=%d\n", success); - e->eapol_test_num_reauths--; - if (e->eapol_test_num_reauths < 0) - eloop_terminate(); - else { - eapol_test_compare_pmk(e); - eloop_register_timeout(0, 100000, eapol_sm_reauth, e, NULL); - } -} - - -static int test_eapol(struct eapol_test_data *e, struct wpa_supplicant *wpa_s, - struct wpa_ssid *ssid) -{ - struct eapol_config eapol_conf; - struct eapol_ctx *ctx; - - ctx = os_zalloc(sizeof(*ctx)); - if (ctx == NULL) { - printf("Failed to allocate EAPOL context.\n"); - return -1; - } - ctx->ctx = wpa_s; - ctx->msg_ctx = wpa_s; - ctx->scard_ctx = wpa_s->scard; - ctx->cb = eapol_sm_cb; - ctx->cb_ctx = e; - ctx->eapol_send_ctx = wpa_s; - ctx->preauth = 0; - ctx->eapol_done_cb = eapol_test_eapol_done_cb; - ctx->eapol_send = eapol_test_eapol_send; - ctx->set_config_blob = eapol_test_set_config_blob; - ctx->get_config_blob = eapol_test_get_config_blob; - ctx->opensc_engine_path = wpa_s->conf->opensc_engine_path; - ctx->pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path; - ctx->pkcs11_module_path = wpa_s->conf->pkcs11_module_path; - - wpa_s->eapol = eapol_sm_init(ctx); - if (wpa_s->eapol == NULL) { - os_free(ctx); - printf("Failed to initialize EAPOL state machines.\n"); - return -1; - } - - wpa_s->current_ssid = ssid; - os_memset(&eapol_conf, 0, sizeof(eapol_conf)); - eapol_conf.accept_802_1x_keys = 1; - eapol_conf.required_keys = 0; - eapol_conf.fast_reauth = wpa_s->conf->fast_reauth; - eapol_conf.workaround = ssid->eap_workaround; - eapol_sm_notify_config(wpa_s->eapol, ssid, &eapol_conf); - eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard); - - - eapol_sm_notify_portValid(wpa_s->eapol, FALSE); - /* 802.1X::portControl = Auto */ - eapol_sm_notify_portEnabled(wpa_s->eapol, TRUE); - - return 0; -} - - -static void test_eapol_clean(struct eapol_test_data *e, - struct wpa_supplicant *wpa_s) -{ - radius_client_deinit(e->radius); - os_free(e->last_eap_radius); - if (e->last_recv_radius) { - radius_msg_free(e->last_recv_radius); - os_free(e->last_recv_radius); - } - os_free(e->eap_identity); - e->eap_identity = NULL; - eapol_sm_deinit(wpa_s->eapol); - wpa_s->eapol = NULL; - if (e->radius_conf && e->radius_conf->auth_server) { - os_free(e->radius_conf->auth_server->shared_secret); - os_free(e->radius_conf->auth_server); - } - os_free(e->radius_conf); - e->radius_conf = NULL; - scard_deinit(wpa_s->scard); - if (wpa_s->ctrl_iface) { - wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface); - wpa_s->ctrl_iface = NULL; - } - wpa_config_free(wpa_s->conf); -} - - -static void send_eap_request_identity(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_supplicant *wpa_s = eloop_ctx; - u8 buf[100], *pos; - struct ieee802_1x_hdr *hdr; - struct eap_hdr *eap; - - hdr = (struct ieee802_1x_hdr *) buf; - hdr->version = EAPOL_VERSION; - hdr->type = IEEE802_1X_TYPE_EAP_PACKET; - hdr->length = htons(5); - - eap = (struct eap_hdr *) (hdr + 1); - eap->code = EAP_CODE_REQUEST; - eap->identifier = 0; - eap->length = htons(5); - pos = (u8 *) (eap + 1); - *pos = EAP_TYPE_IDENTITY; - - printf("Sending fake EAP-Request-Identity\n"); - eapol_sm_rx_eapol(wpa_s->eapol, wpa_s->bssid, buf, - sizeof(*hdr) + 5); -} - - -static void eapol_test_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct eapol_test_data *e = eloop_ctx; - printf("EAPOL test timed out\n"); - e->auth_timed_out = 1; - eloop_terminate(); -} - - -static char *eap_type_text(u8 type) -{ - switch (type) { - case EAP_TYPE_IDENTITY: return "Identity"; - case EAP_TYPE_NOTIFICATION: return "Notification"; - case EAP_TYPE_NAK: return "Nak"; - case EAP_TYPE_TLS: return "TLS"; - case EAP_TYPE_TTLS: return "TTLS"; - case EAP_TYPE_PEAP: return "PEAP"; - case EAP_TYPE_SIM: return "SIM"; - case EAP_TYPE_GTC: return "GTC"; - case EAP_TYPE_MD5: return "MD5"; - case EAP_TYPE_OTP: return "OTP"; - case EAP_TYPE_FAST: return "FAST"; - case EAP_TYPE_SAKE: return "SAKE"; - case EAP_TYPE_PSK: return "PSK"; - default: return "Unknown"; - } -} - - -static void ieee802_1x_decapsulate_radius(struct eapol_test_data *e) -{ - u8 *eap; - size_t len; - struct eap_hdr *hdr; - int eap_type = -1; - char buf[64]; - struct radius_msg *msg; - - if (e->last_recv_radius == NULL) - return; - - msg = e->last_recv_radius; - - eap = radius_msg_get_eap(msg, &len); - if (eap == NULL) { - /* draft-aboba-radius-rfc2869bis-20.txt, Chap. 2.6.3: - * RADIUS server SHOULD NOT send Access-Reject/no EAP-Message - * attribute */ - wpa_printf(MSG_DEBUG, "could not extract " - "EAP-Message from RADIUS message"); - os_free(e->last_eap_radius); - e->last_eap_radius = NULL; - e->last_eap_radius_len = 0; - return; - } - - if (len < sizeof(*hdr)) { - wpa_printf(MSG_DEBUG, "too short EAP packet " - "received from authentication server"); - os_free(eap); - return; - } - - if (len > sizeof(*hdr)) - eap_type = eap[sizeof(*hdr)]; - - hdr = (struct eap_hdr *) eap; - switch (hdr->code) { - case EAP_CODE_REQUEST: - os_snprintf(buf, sizeof(buf), "EAP-Request-%s (%d)", - eap_type >= 0 ? eap_type_text(eap_type) : "??", - eap_type); - break; - case EAP_CODE_RESPONSE: - os_snprintf(buf, sizeof(buf), "EAP Response-%s (%d)", - eap_type >= 0 ? eap_type_text(eap_type) : "??", - eap_type); - break; - case EAP_CODE_SUCCESS: - os_snprintf(buf, sizeof(buf), "EAP Success"); - /* LEAP uses EAP Success within an authentication, so must not - * stop here with eloop_terminate(); */ - break; - case EAP_CODE_FAILURE: - os_snprintf(buf, sizeof(buf), "EAP Failure"); - eloop_terminate(); - break; - default: - os_snprintf(buf, sizeof(buf), "unknown EAP code"); - wpa_hexdump(MSG_DEBUG, "Decapsulated EAP packet", eap, len); - break; - } - wpa_printf(MSG_DEBUG, "decapsulated EAP packet (code=%d " - "id=%d len=%d) from RADIUS server: %s", - hdr->code, hdr->identifier, ntohs(hdr->length), buf); - - /* sta->eapol_sm->be_auth.idFromServer = hdr->identifier; */ - - os_free(e->last_eap_radius); - e->last_eap_radius = eap; - e->last_eap_radius_len = len; - - { - struct ieee802_1x_hdr *dot1x; - dot1x = os_malloc(sizeof(*dot1x) + len); - assert(dot1x != NULL); - dot1x->version = EAPOL_VERSION; - dot1x->type = IEEE802_1X_TYPE_EAP_PACKET; - dot1x->length = htons(len); - os_memcpy((u8 *) (dot1x + 1), eap, len); - eapol_sm_rx_eapol(e->wpa_s->eapol, e->wpa_s->bssid, - (u8 *) dot1x, sizeof(*dot1x) + len); - os_free(dot1x); - } -} - - -static void ieee802_1x_get_keys(struct eapol_test_data *e, - struct radius_msg *msg, struct radius_msg *req, - u8 *shared_secret, size_t shared_secret_len) -{ - struct radius_ms_mppe_keys *keys; - - keys = radius_msg_get_ms_keys(msg, req, shared_secret, - shared_secret_len); - if (keys && keys->send == NULL && keys->recv == NULL) { - os_free(keys); - keys = radius_msg_get_cisco_keys(msg, req, shared_secret, - shared_secret_len); - } - - if (keys) { - if (keys->send) { - wpa_hexdump(MSG_DEBUG, "MS-MPPE-Send-Key (sign)", - keys->send, keys->send_len); - } - if (keys->recv) { - wpa_hexdump(MSG_DEBUG, "MS-MPPE-Recv-Key (crypt)", - keys->recv, keys->recv_len); - e->authenticator_pmk_len = - keys->recv_len > PMK_LEN ? PMK_LEN : - keys->recv_len; - os_memcpy(e->authenticator_pmk, keys->recv, - e->authenticator_pmk_len); - } - - os_free(keys->send); - os_free(keys->recv); - os_free(keys); - } -} - - -/* Process the RADIUS frames from Authentication Server */ -static RadiusRxResult -ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req, - u8 *shared_secret, size_t shared_secret_len, - void *data) -{ - struct eapol_test_data *e = data; - - /* RFC 2869, Ch. 5.13: valid Message-Authenticator attribute MUST be - * present when packet contains an EAP-Message attribute */ - if (msg->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\n"); - } 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_UNKNOWN; - } - - if (msg->hdr->code != RADIUS_CODE_ACCESS_ACCEPT && - msg->hdr->code != RADIUS_CODE_ACCESS_REJECT && - msg->hdr->code != RADIUS_CODE_ACCESS_CHALLENGE) { - printf("Unknown RADIUS message code\n"); - return RADIUS_RX_UNKNOWN; - } - - e->radius_identifier = -1; - wpa_printf(MSG_DEBUG, "RADIUS packet matching with station"); - - if (e->last_recv_radius) { - radius_msg_free(e->last_recv_radius); - os_free(e->last_recv_radius); - } - - e->last_recv_radius = msg; - - switch (msg->hdr->code) { - case RADIUS_CODE_ACCESS_ACCEPT: - e->radius_access_accept_received = 1; - ieee802_1x_get_keys(e, msg, req, shared_secret, - shared_secret_len); - break; - case RADIUS_CODE_ACCESS_REJECT: - e->radius_access_reject_received = 1; - break; - } - - ieee802_1x_decapsulate_radius(e); - - if ((msg->hdr->code == RADIUS_CODE_ACCESS_ACCEPT && - e->eapol_test_num_reauths < 0) || - msg->hdr->code == RADIUS_CODE_ACCESS_REJECT) { - eloop_terminate(); - } - - return RADIUS_RX_QUEUED; -} - - -static void wpa_init_conf(struct eapol_test_data *e, - struct wpa_supplicant *wpa_s, const char *authsrv, - int port, const char *secret) -{ - struct hostapd_radius_server *as; - int res; - - wpa_s->bssid[5] = 1; - os_memcpy(wpa_s->own_addr, e->own_addr, ETH_ALEN); - e->own_ip_addr.s_addr = htonl((127 << 24) | 1); - os_strncpy(wpa_s->ifname, "test", sizeof(wpa_s->ifname)); - - e->radius_conf = os_zalloc(sizeof(struct hostapd_radius_servers)); - assert(e->radius_conf != NULL); - e->radius_conf->num_auth_servers = 1; - as = os_zalloc(sizeof(struct hostapd_radius_server)); - assert(as != NULL); -#if defined(CONFIG_NATIVE_WINDOWS) || defined(CONFIG_ANSI_C_EXTRA) - { - int a[4]; - u8 *pos; - sscanf(authsrv, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]); - pos = (u8 *) &as->addr.u.v4; - *pos++ = a[0]; - *pos++ = a[1]; - *pos++ = a[2]; - *pos++ = a[3]; - } -#else /* CONFIG_NATIVE_WINDOWS or CONFIG_ANSI_C_EXTRA */ - inet_aton(authsrv, &as->addr.u.v4); -#endif /* CONFIG_NATIVE_WINDOWS or CONFIG_ANSI_C_EXTRA */ - as->addr.af = AF_INET; - as->port = port; - as->shared_secret = (u8 *) os_strdup(secret); - as->shared_secret_len = os_strlen(secret); - e->radius_conf->auth_server = as; - e->radius_conf->auth_servers = as; - e->radius_conf->msg_dumps = 1; - - e->radius = radius_client_init(wpa_s, e->radius_conf); - assert(e->radius != NULL); - - res = radius_client_register(e->radius, RADIUS_AUTH, - ieee802_1x_receive_auth, e); - assert(res == 0); -} - - -static int scard_test(void) -{ - struct scard_data *scard; - size_t len; - char imsi[20]; - unsigned char _rand[16]; -#ifdef PCSC_FUNCS - unsigned char sres[4]; - unsigned char kc[8]; -#endif /* PCSC_FUNCS */ -#define num_triplets 5 - unsigned char rand_[num_triplets][16]; - unsigned char sres_[num_triplets][4]; - unsigned char kc_[num_triplets][8]; - int i, res; - size_t j; - -#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 - unsigned char aka_rand[AKA_RAND_LEN]; - unsigned char aka_autn[AKA_AUTN_LEN]; - unsigned char aka_auts[AKA_AUTS_LEN]; - unsigned char aka_res[RES_MAX_LEN]; - size_t aka_res_len; - unsigned char aka_ik[IK_LEN]; - unsigned char aka_ck[CK_LEN]; - - scard = scard_init(SCARD_TRY_BOTH); - if (scard == NULL) - return -1; - if (scard_set_pin(scard, "1234")) { - wpa_printf(MSG_WARNING, "PIN validation failed"); - scard_deinit(scard); - return -1; - } - - len = sizeof(imsi); - if (scard_get_imsi(scard, imsi, &len)) - goto failed; - wpa_hexdump_ascii(MSG_DEBUG, "SCARD: IMSI", (u8 *) imsi, len); - /* NOTE: Permanent Username: 1 | IMSI */ - - os_memset(_rand, 0, sizeof(_rand)); - if (scard_gsm_auth(scard, _rand, sres, kc)) - goto failed; - - os_memset(_rand, 0xff, sizeof(_rand)); - if (scard_gsm_auth(scard, _rand, sres, kc)) - goto failed; - - for (i = 0; i < num_triplets; i++) { - os_memset(rand_[i], i, sizeof(rand_[i])); - if (scard_gsm_auth(scard, rand_[i], sres_[i], kc_[i])) - goto failed; - } - - for (i = 0; i < num_triplets; i++) { - printf("1"); - for (j = 0; j < len; j++) - printf("%c", imsi[j]); - printf(","); - for (j = 0; j < 16; j++) - printf("%02X", rand_[i][j]); - printf(","); - for (j = 0; j < 4; j++) - printf("%02X", sres_[i][j]); - printf(","); - for (j = 0; j < 8; j++) - printf("%02X", kc_[i][j]); - printf("\n"); - } - - wpa_printf(MSG_DEBUG, "Trying to use UMTS authentication"); - - /* seq 39 (0x28) */ - os_memset(aka_rand, 0xaa, 16); - os_memcpy(aka_autn, "\x86\x71\x31\xcb\xa2\xfc\x61\xdf" - "\xa3\xb3\x97\x9d\x07\x32\xa2\x12", 16); - - res = scard_umts_auth(scard, aka_rand, aka_autn, aka_res, &aka_res_len, - aka_ik, aka_ck, aka_auts); - if (res == 0) { - wpa_printf(MSG_DEBUG, "UMTS auth completed successfully"); - wpa_hexdump(MSG_DEBUG, "RES", aka_res, aka_res_len); - wpa_hexdump(MSG_DEBUG, "IK", aka_ik, IK_LEN); - wpa_hexdump(MSG_DEBUG, "CK", aka_ck, CK_LEN); - } else if (res == -2) { - wpa_printf(MSG_DEBUG, "UMTS auth resulted in synchronization " - "failure"); - wpa_hexdump(MSG_DEBUG, "AUTS", aka_auts, AKA_AUTS_LEN); - } else { - wpa_printf(MSG_DEBUG, "UMTS auth failed"); - } - -failed: - scard_deinit(scard); - - return 0; -#undef num_triplets -} - - -static int scard_get_triplets(int argc, char *argv[]) -{ - struct scard_data *scard; - size_t len; - char imsi[20]; - unsigned char _rand[16]; - unsigned char sres[4]; - unsigned char kc[8]; - int num_triplets; - int i; - size_t j; - - if (argc < 2 || ((num_triplets = atoi(argv[1])) <= 0)) { - printf("invalid parameters for sim command\n"); - return -1; - } - - if (argc <= 2 || os_strcmp(argv[2], "debug") != 0) { - /* disable debug output */ - wpa_debug_level = 99; - } - - scard = scard_init(SCARD_GSM_SIM_ONLY); - if (scard == NULL) { - printf("Failed to open smartcard connection\n"); - return -1; - } - if (scard_set_pin(scard, argv[0])) { - wpa_printf(MSG_WARNING, "PIN validation failed"); - scard_deinit(scard); - return -1; - } - - len = sizeof(imsi); - if (scard_get_imsi(scard, imsi, &len)) { - scard_deinit(scard); - return -1; - } - - for (i = 0; i < num_triplets; i++) { - os_memset(_rand, i, sizeof(_rand)); - if (scard_gsm_auth(scard, _rand, sres, kc)) - break; - - /* IMSI:Kc:SRES:RAND */ - for (j = 0; j < len; j++) - printf("%c", imsi[j]); - printf(":"); - for (j = 0; j < 8; j++) - printf("%02X", kc[j]); - printf(":"); - for (j = 0; j < 4; j++) - printf("%02X", sres[j]); - printf(":"); - for (j = 0; j < 16; j++) - printf("%02X", _rand[j]); - printf("\n"); - } - - scard_deinit(scard); - - return 0; -} - - -static void eapol_test_terminate(int sig, void *eloop_ctx, - void *signal_ctx) -{ - struct wpa_supplicant *wpa_s = eloop_ctx; - wpa_msg(wpa_s, MSG_INFO, "Signal %d received - terminating", sig); - eloop_terminate(); -} - - -static void usage(void) -{ - printf("usage:\n" - "eapol_test [-nWS] -c<conf> [-a<AS IP>] [-p<AS port>] " - "[-s<AS secret>] \\\n" - " [-r<count>] [-t<timeout>] [-C<Connect-Info>] \\\n" - " [-M<client MAC address>]\n" - "eapol_test scard\n" - "eapol_test sim <PIN> <num triplets> [debug]\n" - "\n"); - printf("options:\n" - " -c<conf> = configuration file\n" - " -a<AS IP> = IP address of the authentication server, " - "default 127.0.0.1\n" - " -p<AS port> = UDP port of the authentication server, " - "default 1812\n" - " -s<AS secret> = shared secret with the authentication " - "server, default 'radius'\n" - " -r<count> = number of re-authentications\n" - " -W = wait for a control interface monitor before starting\n" - " -S = save configuration after authentiation\n" - " -n = no MPPE keys expected\n" - " -t<timeout> = sets timeout in seconds (default: 30 s)\n" - " -C<Connect-Info> = RADIUS Connect-Info (default: " - "CONNECT 11Mbps 802.11b)\n" - " -M<client MAC address> = Set own MAC address " - "(Calling-Station-Id,\n" - " default: 02:00:00:00:00:01)\n"); -} - - -int main(int argc, char *argv[]) -{ - struct wpa_supplicant wpa_s; - int c, ret = 1, wait_for_monitor = 0, save_config = 0; - char *as_addr = "127.0.0.1"; - int as_port = 1812; - char *as_secret = "radius"; - char *conf = NULL; - int timeout = 30; - - if (os_program_init()) - return -1; - - os_memset(&eapol_test, 0, sizeof(eapol_test)); - eapol_test.connect_info = "CONNECT 11Mbps 802.11b"; - os_memcpy(eapol_test.own_addr, "\x02\x00\x00\x00\x00\x01", ETH_ALEN); - - wpa_debug_level = 0; - wpa_debug_show_keys = 1; - - for (;;) { - c = getopt(argc, argv, "a:c:C:M:np:r:s:St:W"); - if (c < 0) - break; - switch (c) { - case 'a': - as_addr = optarg; - break; - case 'c': - conf = optarg; - break; - case 'C': - eapol_test.connect_info = optarg; - break; - case 'M': - if (hwaddr_aton(optarg, eapol_test.own_addr)) { - usage(); - return -1; - } - break; - case 'n': - eapol_test.no_mppe_keys++; - break; - case 'p': - as_port = atoi(optarg); - break; - case 'r': - eapol_test.eapol_test_num_reauths = atoi(optarg); - break; - case 's': - as_secret = optarg; - break; - case 'S': - save_config++; - break; - case 't': - timeout = atoi(optarg); - break; - case 'W': - wait_for_monitor++; - break; - default: - usage(); - return -1; - } - } - - if (argc > optind && os_strcmp(argv[optind], "scard") == 0) { - return scard_test(); - } - - if (argc > optind && os_strcmp(argv[optind], "sim") == 0) { - return scard_get_triplets(argc - optind - 1, - &argv[optind + 1]); - } - - if (conf == NULL) { - usage(); - printf("Configuration file is required.\n"); - return -1; - } - - if (eap_peer_register_methods()) { - wpa_printf(MSG_ERROR, "Failed to register EAP methods"); - return -1; - } - - if (eloop_init(&wpa_s)) { - wpa_printf(MSG_ERROR, "Failed to initialize event loop"); - return -1; - } - - os_memset(&wpa_s, 0, sizeof(wpa_s)); - eapol_test.wpa_s = &wpa_s; - wpa_s.conf = wpa_config_read(conf); - if (wpa_s.conf == NULL) { - printf("Failed to parse configuration file '%s'.\n", conf); - return -1; - } - if (wpa_s.conf->ssid == NULL) { - printf("No networks defined.\n"); - return -1; - } - - wpa_init_conf(&eapol_test, &wpa_s, as_addr, as_port, as_secret); - wpa_s.ctrl_iface = wpa_supplicant_ctrl_iface_init(&wpa_s); - if (wpa_s.ctrl_iface == NULL) { - printf("Failed to initialize control interface '%s'.\n" - "You may have another eapol_test process already " - "running or the file was\n" - "left by an unclean termination of eapol_test in " - "which case you will need\n" - "to manually remove this file before starting " - "eapol_test again.\n", - wpa_s.conf->ctrl_interface); - return -1; - } - if (wpa_supplicant_scard_init(&wpa_s, wpa_s.conf->ssid)) - return -1; - - if (test_eapol(&eapol_test, &wpa_s, wpa_s.conf->ssid)) - return -1; - - if (wait_for_monitor) - wpa_supplicant_ctrl_iface_wait(wpa_s.ctrl_iface); - - eloop_register_timeout(timeout, 0, eapol_test_timeout, &eapol_test, - NULL); - eloop_register_timeout(0, 0, send_eap_request_identity, &wpa_s, NULL); - eloop_register_signal_terminate(eapol_test_terminate, NULL); - eloop_register_signal_reconfig(eapol_test_terminate, NULL); - eloop_run(); - - eloop_cancel_timeout(eapol_test_timeout, &eapol_test, NULL); - eloop_cancel_timeout(eapol_sm_reauth, &eapol_test, NULL); - - if (eapol_test_compare_pmk(&eapol_test) == 0 || - eapol_test.no_mppe_keys) - ret = 0; - if (eapol_test.auth_timed_out) - ret = -2; - if (eapol_test.radius_access_reject_received) - ret = -3; - - if (save_config) - wpa_config_write(conf, wpa_s.conf); - - test_eapol_clean(&eapol_test, &wpa_s); - - eap_peer_unregister_methods(); - - eloop_destroy(); - - printf("MPPE keys OK: %d mismatch: %d\n", - eapol_test.num_mppe_ok, eapol_test.num_mppe_mismatch); - if (eapol_test.num_mppe_mismatch) - ret = -4; - if (ret) - printf("FAILURE\n"); - else - printf("SUCCESS\n"); - - os_program_deinit(); - - return ret; -} diff --git a/contrib/wpa_supplicant/eloop.c b/contrib/wpa_supplicant/eloop.c deleted file mode 100644 index 9cac792615bb..000000000000 --- a/contrib/wpa_supplicant/eloop.c +++ /dev/null @@ -1,553 +0,0 @@ -/* - * Event loop based on select() loop - * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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; - eloop_sock_handler handler; -}; - -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_sock_table { - int count; - struct eloop_sock *table; - int changed; -}; - -struct eloop_data { - void *user_data; - - int max_sock; - - struct eloop_sock_table readers; - struct eloop_sock_table writers; - struct eloop_sock_table exceptions; - - 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 *user_data) -{ - os_memset(&eloop, 0, sizeof(eloop)); - eloop.user_data = user_data; - 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; - - 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; - table->count++; - table->table = tmp; - if (sock > eloop.max_sock) - eloop.max_sock = sock; - table->changed = 1; - - 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; - 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; -} - - -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) - 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, *prev; - - timeout = os_malloc(sizeof(*timeout)); - if (timeout == NULL) - return -1; - if (os_get_time(&timeout->time) < 0) { - os_free(timeout); - return -1; - } - 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(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; -} - - -#ifndef CONFIG_NATIVE_WINDOWS -static void eloop_handle_alarm(int sig) -{ - fprintf(stderr, "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.user_data, - 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) { - printf("eloop_run - malloc failed\n"); - goto out; - } - - while (!eloop.terminate && - (eloop.timeout || eloop.readers.count > 0 || - eloop.writers.count > 0 || eloop.exceptions.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; -#if 0 - printf("next timeout in %lu.%06lu sec\n", - tv.sec, tv.usec); -#endif - _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, - eloop.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 */ - 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 (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; - - timeout = eloop.timeout; - while (timeout != NULL) { - prev = timeout; - timeout = timeout->next; - os_free(prev); - } - 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); -} - - -void * eloop_get_user_data(void) -{ - return eloop.user_data; -} diff --git a/contrib/wpa_supplicant/eloop.h b/contrib/wpa_supplicant/eloop.h deleted file mode 100644 index cf83f3836555..000000000000 --- a/contrib/wpa_supplicant/eloop.h +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Event loop - * Copyright (c) 2002-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 - * @eloop_ctx: Registered callback context data (global user_data from - * eloop_init() call) - * @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 *eloop_ctx, - void *signal_ctx); - -/** - * eloop_init() - Initialize global event loop data - * @user_data: Pointer to global data passed as eloop_ctx to signal handlers - * Returns: 0 on success, -1 on failure - * - * This function must be called before any other eloop_* function. user_data - * can be used to configure a global (to the process) pointer that will be - * passed as eloop_ctx parameter to signal handlers. - */ -int eloop_init(void *user_data); - -/** - * 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 <handler,eloop_data,user_data> 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 <handler,eloop_data,user_data> 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. - * - * Signals are 'global' events and there is no local eloop_data pointer like - * with other handlers. The global user_data pointer registered with - * eloop_init() will be used as eloop_ctx for signal handlers. - */ -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. - * - * Signals are 'global' events and there is no local eloop_data pointer like - * with other handlers. The global user_data pointer registered with - * eloop_init() will be used as eloop_ctx for signal handlers. - * - * 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. - * - * Signals are 'global' events and there is no local eloop_data pointer like - * with other handlers. The global user_data pointer registered with - * eloop_init() will be used as eloop_ctx for signal handlers. - * - * 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); - -/** - * eloop_get_user_data - Get global user data - * Returns: user_data pointer that was registered with eloop_init() - */ -void * eloop_get_user_data(void); - -#endif /* ELOOP_H */ diff --git a/contrib/wpa_supplicant/eloop_none.c b/contrib/wpa_supplicant/eloop_none.c deleted file mode 100644 index 215030b2135f..000000000000 --- a/contrib/wpa_supplicant/eloop_none.c +++ /dev/null @@ -1,410 +0,0 @@ -/* - * Event loop - empty template (basic structure, but no OS specific operations) - * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 { - void *user_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 *user_data) -{ - memset(&eloop, 0, sizeof(eloop)); - eloop.user_data = user_data; - 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 - */ -} - - -void * eloop_get_user_data(void) -{ - return eloop.user_data; -} diff --git a/contrib/wpa_supplicant/events.c b/contrib/wpa_supplicant/events.c deleted file mode 100644 index 92dd61dea880..000000000000 --- a/contrib/wpa_supplicant/events.c +++ /dev/null @@ -1,900 +0,0 @@ -/* - * WPA Supplicant - Driver event processing - * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * $FreeBSD$ - */ - -#include "includes.h" - -#include "common.h" -#include "eapol_sm.h" -#include "wpa.h" -#include "eloop.h" -#include "wpa_supplicant.h" -#include "config.h" -#include "l2_packet.h" -#include "wpa_supplicant_i.h" -#include "pcsc_funcs.h" -#include "preauth.h" -#include "pmksa_cache.h" -#include "wpa_ctrl.h" -#include "eap.h" -#include "ctrl_iface_dbus.h" - - -static int wpa_supplicant_select_config(struct wpa_supplicant *wpa_s) -{ - struct wpa_ssid *ssid; - - if (wpa_s->conf->ap_scan == 1 && wpa_s->current_ssid) - return 0; - - ssid = wpa_supplicant_get_ssid(wpa_s); - if (ssid == NULL) { - wpa_printf(MSG_INFO, "No network configuration found for the " - "current AP"); - return -1; - } - - if (ssid->disabled) { - wpa_printf(MSG_DEBUG, "Selected network is disabled"); - return -1; - } - - wpa_printf(MSG_DEBUG, "Network configuration found for the current " - "AP"); - if (ssid->key_mgmt & (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_IEEE8021X | - WPA_KEY_MGMT_WPA_NONE)) { - u8 wpa_ie[80]; - size_t wpa_ie_len = sizeof(wpa_ie); - wpa_supplicant_set_suites(wpa_s, NULL, ssid, - wpa_ie, &wpa_ie_len); - } else { - wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); - } - - if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) - eapol_sm_invalidate_cached_session(wpa_s->eapol); - wpa_s->current_ssid = ssid; - wpa_sm_set_config(wpa_s->wpa, wpa_s->current_ssid); - wpa_supplicant_initiate_eapol(wpa_s); - - return 0; -} - - -static void wpa_supplicant_stop_countermeasures(void *eloop_ctx, - void *sock_ctx) -{ - struct wpa_supplicant *wpa_s = eloop_ctx; - - if (wpa_s->countermeasures) { - wpa_s->countermeasures = 0; - wpa_drv_set_countermeasures(wpa_s, 0); - wpa_msg(wpa_s, MSG_INFO, "WPA: TKIP countermeasures stopped"); - wpa_supplicant_req_scan(wpa_s, 0, 0); - } -} - - -void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s) -{ - wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); - os_memset(wpa_s->bssid, 0, ETH_ALEN); - os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); - eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); - eapol_sm_notify_portValid(wpa_s->eapol, FALSE); - if (wpa_s->key_mgmt == WPA_KEY_MGMT_PSK) - eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); -} - - -static void wpa_find_assoc_pmkid(struct wpa_supplicant *wpa_s) -{ - struct wpa_ie_data ie; - int i, pmksa_set = -1; - - if (wpa_sm_parse_own_wpa_ie(wpa_s->wpa, &ie) < 0 || - ie.pmkid == NULL) - return; - - for (i = 0; i < ie.num_pmkid; i++) { - pmksa_set = pmksa_cache_set_current(wpa_s->wpa, - ie.pmkid + i * PMKID_LEN, - NULL, NULL, 0); - if (pmksa_set == 0) { - eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1); - break; - } - } - - wpa_printf(MSG_DEBUG, "RSN: PMKID from assoc IE %sfound from PMKSA " - "cache", pmksa_set == 0 ? "" : "not "); -} - - -static void wpa_supplicant_event_pmkid_candidate(struct wpa_supplicant *wpa_s, - union wpa_event_data *data) -{ - if (data == NULL) { - wpa_printf(MSG_DEBUG, "RSN: No data in PMKID candidate event"); - return; - } - wpa_printf(MSG_DEBUG, "RSN: PMKID candidate event - bssid=" MACSTR - " index=%d preauth=%d", - MAC2STR(data->pmkid_candidate.bssid), - data->pmkid_candidate.index, - data->pmkid_candidate.preauth); - - pmksa_candidate_add(wpa_s->wpa, data->pmkid_candidate.bssid, - data->pmkid_candidate.index, - data->pmkid_candidate.preauth); -} - - -static int wpa_supplicant_dynamic_keys(struct wpa_supplicant *wpa_s) -{ - if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE || - wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) - return 0; - -#ifdef IEEE8021X_EAPOL - if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA && - wpa_s->current_ssid && - !(wpa_s->current_ssid->eapol_flags & - (EAPOL_FLAG_REQUIRE_KEY_UNICAST | - EAPOL_FLAG_REQUIRE_KEY_BROADCAST))) { - /* IEEE 802.1X, but not using dynamic WEP keys (i.e., either - * plaintext or static WEP keys). */ - return 0; - } -#endif /* IEEE8021X_EAPOL */ - - return 1; -} - - -/** - * wpa_supplicant_scard_init - Initialize SIM/USIM access with PC/SC - * @wpa_s: pointer to wpa_supplicant data - * @ssid: Configuration data for the network - * Returns: 0 on success, -1 on failure - * - * This function is called when starting authentication with a network that is - * configured to use PC/SC for SIM/USIM access (EAP-SIM or EAP-AKA). - */ -int wpa_supplicant_scard_init(struct wpa_supplicant *wpa_s, - struct wpa_ssid *ssid) -{ -#ifdef IEEE8021X_EAPOL - int aka = 0, sim = 0, type; - - if (ssid->pcsc == NULL || wpa_s->scard != NULL) - return 0; - - if (ssid->eap_methods == NULL) { - sim = 1; - aka = 1; - } else { - struct eap_method_type *eap = ssid->eap_methods; - while (eap->vendor != EAP_VENDOR_IETF || - eap->method != EAP_TYPE_NONE) { - if (eap->vendor == EAP_VENDOR_IETF) { - if (eap->method == EAP_TYPE_SIM) - sim = 1; - else if (eap->method == EAP_TYPE_AKA) - aka = 1; - } - eap++; - } - } - - if (eap_sm_get_eap_methods(EAP_VENDOR_IETF, EAP_TYPE_SIM) == NULL) - sim = 0; - if (eap_sm_get_eap_methods(EAP_VENDOR_IETF, EAP_TYPE_AKA) == NULL) - aka = 0; - - if (!sim && !aka) { - wpa_printf(MSG_DEBUG, "Selected network is configured to use " - "SIM, but neither EAP-SIM nor EAP-AKA are enabled"); - return 0; - } - - wpa_printf(MSG_DEBUG, "Selected network is configured to use SIM " - "(sim=%d aka=%d) - initialize PCSC", sim, aka); - if (sim && aka) - type = SCARD_TRY_BOTH; - else if (aka) - type = SCARD_USIM_ONLY; - else - type = SCARD_GSM_SIM_ONLY; - - wpa_s->scard = scard_init(type); - if (wpa_s->scard == NULL) { - wpa_printf(MSG_WARNING, "Failed to initialize SIM " - "(pcsc-lite)"); - return -1; - } - wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard); - eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard); -#endif /* IEEE8021X_EAPOL */ - - return 0; -} - - -static int wpa_supplicant_match_privacy(struct wpa_scan_result *bss, - struct wpa_ssid *ssid) -{ - int i, privacy = 0; - - if (ssid->mixed_cell) - return 1; - - for (i = 0; i < NUM_WEP_KEYS; i++) { - if (ssid->wep_key_len[i]) { - privacy = 1; - break; - } - } -#ifdef IEEE8021X_EAPOL - if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && - ssid->eapol_flags & (EAPOL_FLAG_REQUIRE_KEY_UNICAST | - EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) - privacy = 1; -#endif /* IEEE8021X_EAPOL */ - - if (bss->caps & IEEE80211_CAP_PRIVACY) - return privacy; - return !privacy; -} - - -static int wpa_supplicant_ssid_bss_match(struct wpa_ssid *ssid, - struct wpa_scan_result *bss) -{ - struct wpa_ie_data ie; - int proto_match = 0; - - while ((ssid->proto & WPA_PROTO_RSN) && bss->rsn_ie_len > 0) { - proto_match++; - - if (wpa_parse_wpa_ie(bss->rsn_ie, bss->rsn_ie_len, &ie)) { - wpa_printf(MSG_DEBUG, " skip RSN IE - parse failed"); - break; - } - if (!(ie.proto & ssid->proto)) { - wpa_printf(MSG_DEBUG, " skip RSN IE - proto " - "mismatch"); - break; - } - - if (!(ie.pairwise_cipher & ssid->pairwise_cipher)) { - wpa_printf(MSG_DEBUG, " skip RSN IE - PTK cipher " - "mismatch"); - break; - } - - if (!(ie.group_cipher & ssid->group_cipher)) { - wpa_printf(MSG_DEBUG, " skip RSN IE - GTK cipher " - "mismatch"); - break; - } - - if (!(ie.key_mgmt & ssid->key_mgmt)) { - wpa_printf(MSG_DEBUG, " skip RSN IE - key mgmt " - "mismatch"); - break; - } - -#ifdef CONFIG_IEEE80211W - if (!(ie.capabilities & WPA_CAPABILITY_MGMT_FRAME_PROTECTION) - && ssid->ieee80211w == IEEE80211W_REQUIRED) { - wpa_printf(MSG_DEBUG, " skip RSN IE - no mgmt frame " - "protection"); - break; - } -#endif /* CONFIG_IEEE80211W */ - - wpa_printf(MSG_DEBUG, " selected based on RSN IE"); - return 1; - } - - while ((ssid->proto & WPA_PROTO_WPA) && bss->wpa_ie_len > 0) { - proto_match++; - - if (wpa_parse_wpa_ie(bss->wpa_ie, bss->wpa_ie_len, &ie)) { - wpa_printf(MSG_DEBUG, " skip WPA IE - parse failed"); - break; - } - if (!(ie.proto & ssid->proto)) { - wpa_printf(MSG_DEBUG, " skip WPA IE - proto " - "mismatch"); - break; - } - - if (!(ie.pairwise_cipher & ssid->pairwise_cipher)) { - wpa_printf(MSG_DEBUG, " skip WPA IE - PTK cipher " - "mismatch"); - break; - } - - if (!(ie.group_cipher & ssid->group_cipher)) { - wpa_printf(MSG_DEBUG, " skip WPA IE - GTK cipher " - "mismatch"); - break; - } - - if (!(ie.key_mgmt & ssid->key_mgmt)) { - wpa_printf(MSG_DEBUG, " skip WPA IE - key mgmt " - "mismatch"); - break; - } - - wpa_printf(MSG_DEBUG, " selected based on WPA IE"); - return 1; - } - - if (proto_match == 0) - wpa_printf(MSG_DEBUG, " skip - no WPA/RSN proto match"); - - return 0; -} - - -static struct wpa_scan_result * -wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s, struct wpa_ssid *group, - struct wpa_scan_result *results, int num, - struct wpa_ssid **selected_ssid) -{ - struct wpa_ssid *ssid; - struct wpa_scan_result *bss, *selected = NULL; - int i; - struct wpa_blacklist *e; - - wpa_printf(MSG_DEBUG, "Selecting BSS from priority group %d", - group->priority); - - bss = NULL; - ssid = NULL; - /* First, try to find WPA-enabled AP */ - wpa_printf(MSG_DEBUG, "Try to find WPA-enabled AP"); - for (i = 0; i < num && !selected; i++) { - bss = &results[i]; - wpa_printf(MSG_DEBUG, "%d: " MACSTR " ssid='%s' " - "wpa_ie_len=%lu rsn_ie_len=%lu caps=0x%x", - i, MAC2STR(bss->bssid), - wpa_ssid_txt(bss->ssid, bss->ssid_len), - (unsigned long) bss->wpa_ie_len, - (unsigned long) bss->rsn_ie_len, bss->caps); - e = wpa_blacklist_get(wpa_s, bss->bssid); - if (e && e->count > 1) { - wpa_printf(MSG_DEBUG, " skip - blacklisted"); - continue; - } - - if (bss->wpa_ie_len == 0 && bss->rsn_ie_len == 0) { - wpa_printf(MSG_DEBUG, " skip - no WPA/RSN IE"); - continue; - } - - for (ssid = group; ssid; ssid = ssid->pnext) { - if (ssid->disabled) { - wpa_printf(MSG_DEBUG, " skip - disabled"); - continue; - } - if (bss->ssid_len != ssid->ssid_len || - os_memcmp(bss->ssid, ssid->ssid, - bss->ssid_len) != 0) { - wpa_printf(MSG_DEBUG, " skip - " - "SSID mismatch"); - continue; - } - if (ssid->bssid_set && - os_memcmp(bss->bssid, ssid->bssid, ETH_ALEN) != 0) - { - wpa_printf(MSG_DEBUG, " skip - " - "BSSID mismatch"); - continue; - } - if (wpa_supplicant_ssid_bss_match(ssid, bss)) { - selected = bss; - *selected_ssid = ssid; - wpa_printf(MSG_DEBUG, " selected WPA AP " - MACSTR " ssid='%s'", - MAC2STR(bss->bssid), - wpa_ssid_txt(bss->ssid, - bss->ssid_len)); - break; - } - } - } - - /* If no WPA-enabled AP found, try to find non-WPA AP, if configuration - * allows this. */ - wpa_printf(MSG_DEBUG, "Try to find non-WPA AP"); - for (i = 0; i < num && !selected; i++) { - bss = &results[i]; - wpa_printf(MSG_DEBUG, "%d: " MACSTR " ssid='%s' " - "wpa_ie_len=%lu rsn_ie_len=%lu caps=0x%x", - i, MAC2STR(bss->bssid), - wpa_ssid_txt(bss->ssid, bss->ssid_len), - (unsigned long) bss->wpa_ie_len, - (unsigned long) bss->rsn_ie_len, bss->caps); - e = wpa_blacklist_get(wpa_s, bss->bssid); - if (e && e->count > 1) { - wpa_printf(MSG_DEBUG, " skip - blacklisted"); - continue; - } - for (ssid = group; ssid; ssid = ssid->pnext) { - if (ssid->disabled) { - wpa_printf(MSG_DEBUG, " skip - disabled"); - continue; - } - if (ssid->ssid_len != 0 && - (bss->ssid_len != ssid->ssid_len || - os_memcmp(bss->ssid, ssid->ssid, - bss->ssid_len) != 0)) { - wpa_printf(MSG_DEBUG, " skip - " - "SSID mismatch"); - continue; - } - - if (ssid->bssid_set && - os_memcmp(bss->bssid, ssid->bssid, ETH_ALEN) != 0) - { - wpa_printf(MSG_DEBUG, " skip - " - "BSSID mismatch"); - continue; - } - - if (!(ssid->key_mgmt & WPA_KEY_MGMT_NONE) && - !(ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)) - { - wpa_printf(MSG_DEBUG, " skip - " - "non-WPA network not allowed"); - continue; - } - - if ((ssid->key_mgmt & - (WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_PSK)) && - (bss->wpa_ie_len != 0 || bss->rsn_ie_len != 0)) { - wpa_printf(MSG_DEBUG, " skip - " - "WPA network"); - continue; - } - - if (!wpa_supplicant_match_privacy(bss, ssid)) { - wpa_printf(MSG_DEBUG, " skip - " - "privacy mismatch"); - continue; - } - - if (bss->caps & IEEE80211_CAP_IBSS) { - wpa_printf(MSG_DEBUG, " skip - " - "IBSS (adhoc) network"); - continue; - } - - selected = bss; - *selected_ssid = ssid; - wpa_printf(MSG_DEBUG, " selected non-WPA AP " - MACSTR " ssid='%s'", - MAC2STR(bss->bssid), - wpa_ssid_txt(bss->ssid, bss->ssid_len)); - break; - } - } - - return selected; -} - - -static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s) -{ - int num, prio, timeout; - struct wpa_scan_result *selected = NULL; - struct wpa_ssid *ssid = NULL; - struct wpa_scan_result *results; - - if (wpa_supplicant_get_scan_results(wpa_s) < 0) { - if (wpa_s->conf->ap_scan == 2) - return; - wpa_printf(MSG_DEBUG, "Failed to get scan results - try " - "scanning again"); - timeout = 1; - goto req_scan; - } - - wpa_supplicant_dbus_notify_scan_results(wpa_s); - - if (wpa_s->conf->ap_scan == 2 || wpa_s->disconnected) - return; - results = wpa_s->scan_results; - num = wpa_s->num_scan_results; - - while (selected == NULL) { - for (prio = 0; prio < wpa_s->conf->num_prio; prio++) { - selected = wpa_supplicant_select_bss( - wpa_s, wpa_s->conf->pssid[prio], results, num, - &ssid); - if (selected) - break; - } - - if (selected == NULL && wpa_s->blacklist) { - wpa_printf(MSG_DEBUG, "No APs found - clear blacklist " - "and try again"); - wpa_blacklist_clear(wpa_s); - } else if (selected == NULL) { - break; - } - } - - if (selected) { - /* Do not trigger new association unless the BSSID has changed - * or if reassociation is requested. If we are in process of - * associating with the selected BSSID, do not trigger new - * attempt. */ - if (wpa_s->reassociate || - (os_memcmp(selected->bssid, wpa_s->bssid, ETH_ALEN) != 0 && - (wpa_s->wpa_state != WPA_ASSOCIATING || - os_memcmp(selected->bssid, wpa_s->pending_bssid, - ETH_ALEN) != 0))) { - if (wpa_supplicant_scard_init(wpa_s, ssid)) { - wpa_supplicant_req_scan(wpa_s, 10, 0); - return; - } - wpa_supplicant_associate(wpa_s, selected, ssid); - } else { - wpa_printf(MSG_DEBUG, "Already associated with the " - "selected AP."); - } - rsn_preauth_scan_results(wpa_s->wpa, results, num); - } else { - wpa_printf(MSG_DEBUG, "No suitable AP found."); - timeout = 5; - goto req_scan; - } - - return; - -req_scan: - if (wpa_s->scan_res_tried == 1 && wpa_s->conf->ap_scan == 1) { - /* - * Quick recovery if the initial scan results were not - * complete when fetched before the first scan request. - */ - wpa_s->scan_res_tried++; - timeout = 0; - } - wpa_supplicant_req_scan(wpa_s, timeout, 0); -} - - -static void wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s, - union wpa_event_data *data) -{ - int l, len, found = 0, wpa_found, rsn_found; - u8 *p; - - wpa_printf(MSG_DEBUG, "Association info event"); - if (data->assoc_info.req_ies) - wpa_hexdump(MSG_DEBUG, "req_ies", data->assoc_info.req_ies, - data->assoc_info.req_ies_len); - if (data->assoc_info.resp_ies) - wpa_hexdump(MSG_DEBUG, "resp_ies", data->assoc_info.resp_ies, - data->assoc_info.resp_ies_len); - if (data->assoc_info.beacon_ies) - wpa_hexdump(MSG_DEBUG, "beacon_ies", - data->assoc_info.beacon_ies, - data->assoc_info.beacon_ies_len); - - p = data->assoc_info.req_ies; - l = data->assoc_info.req_ies_len; - - /* Go through the IEs and make a copy of the WPA/RSN IE, if present. */ - while (p && l >= 2) { - len = p[1] + 2; - if (len > l) { - wpa_hexdump(MSG_DEBUG, "Truncated IE in assoc_info", - p, l); - break; - } - if ((p[0] == GENERIC_INFO_ELEM && p[1] >= 6 && - (os_memcmp(&p[2], "\x00\x50\xF2\x01\x01\x00", 6) == 0)) || - (p[0] == RSN_INFO_ELEM && p[1] >= 2)) { - if (wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, p, len)) - break; - found = 1; - wpa_find_assoc_pmkid(wpa_s); - break; - } - l -= len; - p += len; - } - if (!found && data->assoc_info.req_ies) - wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0); - - /* WPA/RSN IE from Beacon/ProbeResp */ - p = data->assoc_info.beacon_ies; - l = data->assoc_info.beacon_ies_len; - - /* Go through the IEs and make a copy of the WPA/RSN IEs, if present. - */ - wpa_found = rsn_found = 0; - while (p && l >= 2) { - len = p[1] + 2; - if (len > l) { - wpa_hexdump(MSG_DEBUG, "Truncated IE in beacon_ies", - p, l); - break; - } - if (!wpa_found && - p[0] == GENERIC_INFO_ELEM && p[1] >= 6 && - os_memcmp(&p[2], "\x00\x50\xF2\x01\x01\x00", 6) == 0) { - wpa_found = 1; - wpa_sm_set_ap_wpa_ie(wpa_s->wpa, p, len); - } - - if (!rsn_found && - p[0] == RSN_INFO_ELEM && p[1] >= 2) { - rsn_found = 1; - wpa_sm_set_ap_rsn_ie(wpa_s->wpa, p, len); - } - - l -= len; - p += len; - } - - if (!wpa_found && data->assoc_info.beacon_ies) - wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0); - if (!rsn_found && data->assoc_info.beacon_ies) - wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0); -} - - -static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, - union wpa_event_data *data) -{ - u8 bssid[ETH_ALEN]; - - if (data) - wpa_supplicant_event_associnfo(wpa_s, data); - - wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATED); - if (wpa_s->use_client_mlme) - os_memcpy(bssid, wpa_s->bssid, ETH_ALEN); - if (wpa_s->use_client_mlme || - (wpa_drv_get_bssid(wpa_s, bssid) >= 0 && - os_memcmp(bssid, wpa_s->bssid, ETH_ALEN) != 0)) { - wpa_msg(wpa_s, MSG_DEBUG, "Associated to a new BSS: BSSID=" - MACSTR, MAC2STR(bssid)); - os_memcpy(wpa_s->bssid, bssid, ETH_ALEN); - os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); - if (wpa_supplicant_dynamic_keys(wpa_s)) { - wpa_clear_keys(wpa_s, bssid); - } - if (wpa_supplicant_select_config(wpa_s) < 0) { - wpa_supplicant_disassociate(wpa_s, - REASON_DEAUTH_LEAVING); - return; - } - } - - wpa_msg(wpa_s, MSG_INFO, "Associated with " MACSTR, MAC2STR(bssid)); - if (wpa_s->current_ssid) { - /* When using scanning (ap_scan=1), SIM PC/SC interface can be - * initialized before association, but for other modes, - * initialize PC/SC here, if the current configuration needs - * smartcard or SIM/USIM. */ - wpa_supplicant_scard_init(wpa_s, wpa_s->current_ssid); - } - wpa_sm_notify_assoc(wpa_s->wpa, bssid); - l2_packet_notify_auth_start(wpa_s->l2); - - /* - * Set portEnabled first to FALSE in order to get EAP state machine out - * of the SUCCESS state and eapSuccess cleared. Without this, EAPOL PAE - * state machine may transit to AUTHENTICATING state based on obsolete - * eapSuccess and then trigger BE_AUTH to SUCCESS and PAE to - * AUTHENTICATED without ever giving chance to EAP state machine to - * reset the state. - */ - eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); - eapol_sm_notify_portValid(wpa_s->eapol, FALSE); - if (wpa_s->key_mgmt == WPA_KEY_MGMT_PSK) - eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); - /* 802.1X::portControl = Auto */ - eapol_sm_notify_portEnabled(wpa_s->eapol, TRUE); - wpa_s->eapol_received = 0; - if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE || - wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) { - wpa_supplicant_cancel_auth_timeout(wpa_s); - wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); - } else { - /* Timeout for receiving the first EAPOL packet */ - wpa_supplicant_req_auth_timeout(wpa_s, 10, 0); - } - wpa_supplicant_cancel_scan(wpa_s); -} - - -static void wpa_supplicant_event_disassoc(struct wpa_supplicant *wpa_s) -{ - const u8 *bssid; - - if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) { - /* - * At least Host AP driver and a Prism3 card seemed to be - * generating streams of disconnected events when configuring - * IBSS for WPA-None. Ignore them for now. - */ - wpa_printf(MSG_DEBUG, "Disconnect event - ignore in " - "IBSS/WPA-None mode"); - return; - } - - if (wpa_s->wpa_state == WPA_4WAY_HANDSHAKE && - wpa_s->key_mgmt == WPA_KEY_MGMT_PSK) { - wpa_msg(wpa_s, MSG_INFO, "WPA: 4-Way Handshake failed - " - "pre-shared key may be incorrect"); - } - if (wpa_s->wpa_state >= WPA_ASSOCIATED) - wpa_supplicant_req_scan(wpa_s, 0, 100000); - bssid = wpa_s->bssid; - if (os_memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0) - bssid = wpa_s->pending_bssid; - wpa_blacklist_add(wpa_s, bssid); - wpa_sm_notify_disassoc(wpa_s->wpa); - wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "- Disconnect event - " - "remove keys"); - if (wpa_supplicant_dynamic_keys(wpa_s)) { - wpa_s->keys_cleared = 0; - wpa_clear_keys(wpa_s, wpa_s->bssid); - } - wpa_supplicant_mark_disassoc(wpa_s); -} - - -static void -wpa_supplicant_event_michael_mic_failure(struct wpa_supplicant *wpa_s, - union wpa_event_data *data) -{ - int pairwise; - struct os_time t; - - wpa_msg(wpa_s, MSG_WARNING, "Michael MIC failure detected"); - pairwise = (data && data->michael_mic_failure.unicast); - wpa_sm_key_request(wpa_s->wpa, 1, pairwise); - os_get_time(&t); - if (wpa_s->last_michael_mic_error && - t.sec - wpa_s->last_michael_mic_error <= 60) { - /* initialize countermeasures */ - wpa_s->countermeasures = 1; - wpa_msg(wpa_s, MSG_WARNING, "TKIP countermeasures started"); - - /* - * Need to wait for completion of request frame. We do not get - * any callback for the message completion, so just wait a - * short while and hope for the best. */ - os_sleep(0, 10000); - - wpa_drv_set_countermeasures(wpa_s, 1); - wpa_supplicant_deauthenticate(wpa_s, - REASON_MICHAEL_MIC_FAILURE); - eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, - wpa_s, NULL); - eloop_register_timeout(60, 0, - wpa_supplicant_stop_countermeasures, - wpa_s, NULL); - /* TODO: mark the AP rejected for 60 second. STA is - * allowed to associate with another AP.. */ - } - wpa_s->last_michael_mic_error = t.sec; -} - - -#ifdef CONFIG_TERMINATE_ONLASTIF -static int any_interfaces(struct wpa_supplicant *head) -{ - struct wpa_supplicant *wpa_s; - - for (wpa_s = head; wpa_s != NULL; wpa_s = wpa_s->next) - if (!wpa_s->interface_removed) - return 1; - return 0; -} -#endif /* CONFIG_TERMINATE_ONLASTIF */ - -static void -wpa_supplicant_event_interface_status(struct wpa_supplicant *wpa_s, - union wpa_event_data *data) -{ - if (os_strcmp(wpa_s->ifname, data->interface_status.ifname) != 0) - return; - - switch (data->interface_status.ievent) { - case EVENT_INTERFACE_ADDED: - if (!wpa_s->interface_removed) - break; - wpa_s->interface_removed = 0; - wpa_printf(MSG_DEBUG, "Configured interface was added."); - if (wpa_supplicant_driver_init(wpa_s, 1) < 0) { - wpa_printf(MSG_INFO, "Failed to initialize the driver " - "after interface was added."); - } - break; - case EVENT_INTERFACE_REMOVED: - wpa_printf(MSG_DEBUG, "Configured interface was removed."); - wpa_s->interface_removed = 1; - wpa_supplicant_mark_disassoc(wpa_s); - l2_packet_deinit(wpa_s->l2); - wpa_s->l2 = NULL; -#ifdef CONFIG_TERMINATE_ONLASTIF - /* check if last interface */ - if (!any_interfaces(wpa_s->global->ifaces)) - eloop_terminate(); -#endif /* CONFIG_TERMINATE_ONLASTIF */ - break; - } -} - - -#ifdef CONFIG_PEERKEY -static void -wpa_supplicant_event_stkstart(struct wpa_supplicant *wpa_s, - union wpa_event_data *data) -{ - if (data == NULL) - return; - wpa_sm_stkstart(wpa_s->wpa, data->stkstart.peer); -} -#endif /* CONFIG_PEERKEY */ - - -void wpa_supplicant_event(struct wpa_supplicant *wpa_s, wpa_event_type event, - union wpa_event_data *data) -{ - switch (event) { - case EVENT_ASSOC: - wpa_supplicant_event_assoc(wpa_s, data); - break; - case EVENT_DISASSOC: - wpa_supplicant_event_disassoc(wpa_s); - break; - case EVENT_MICHAEL_MIC_FAILURE: - wpa_supplicant_event_michael_mic_failure(wpa_s, data); - break; - case EVENT_SCAN_RESULTS: - wpa_supplicant_event_scan_results(wpa_s); - break; - case EVENT_ASSOCINFO: - wpa_supplicant_event_associnfo(wpa_s, data); - break; - case EVENT_INTERFACE_STATUS: - wpa_supplicant_event_interface_status(wpa_s, data); - break; - case EVENT_PMKID_CANDIDATE: - wpa_supplicant_event_pmkid_candidate(wpa_s, data); - break; -#ifdef CONFIG_PEERKEY - case EVENT_STKSTART: - wpa_supplicant_event_stkstart(wpa_s, data); - break; -#endif /* CONFIG_PEERKEY */ - default: - wpa_printf(MSG_INFO, "Unknown event %d", event); - break; - } -} diff --git a/contrib/wpa_supplicant/examples/ieee8021x.conf b/contrib/wpa_supplicant/examples/ieee8021x.conf deleted file mode 100644 index e8a5503d8359..000000000000 --- a/contrib/wpa_supplicant/examples/ieee8021x.conf +++ /dev/null @@ -1,13 +0,0 @@ -# IEEE 802.1X with dynamic WEP keys using EAP-PEAP/MSCHAPv2 - -ctrl_interface=/var/run/wpa_supplicant - -network={ - ssid="example 802.1x network" - key_mgmt=IEEE8021X - eap=PEAP - phase2="auth=MSCHAPV2" - identity="user name" - password="password" - ca_cert="/etc/cert/ca.pem" -} diff --git a/contrib/wpa_supplicant/examples/plaintext.conf b/contrib/wpa_supplicant/examples/plaintext.conf deleted file mode 100644 index 542ac1dd3b96..000000000000 --- a/contrib/wpa_supplicant/examples/plaintext.conf +++ /dev/null @@ -1,8 +0,0 @@ -# Plaintext (no encryption) network - -ctrl_interface=/var/run/wpa_supplicant - -network={ - ssid="example open network" - key_mgmt=NONE -} diff --git a/contrib/wpa_supplicant/examples/wep.conf b/contrib/wpa_supplicant/examples/wep.conf deleted file mode 100644 index 9c7b55f2722a..000000000000 --- a/contrib/wpa_supplicant/examples/wep.conf +++ /dev/null @@ -1,11 +0,0 @@ -# Static WEP keys - -ctrl_interface=/var/run/wpa_supplicant - -network={ - ssid="example wep network" - key_mgmt=NONE - wep_key0="abcde" - wep_key1=0102030405 - wep_tx_keyidx=0 -} diff --git a/contrib/wpa_supplicant/examples/wpa-psk-tkip.conf b/contrib/wpa_supplicant/examples/wpa-psk-tkip.conf deleted file mode 100644 index 93d7fc2444ea..000000000000 --- a/contrib/wpa_supplicant/examples/wpa-psk-tkip.conf +++ /dev/null @@ -1,12 +0,0 @@ -# WPA-PSK/TKIP - -ctrl_interface=/var/run/wpa_supplicant - -network={ - ssid="example wpa-psk network" - key_mgmt=WPA-PSK - proto=WPA - pairwise=TKIP - group=TKIP - psk="secret passphrase" -} diff --git a/contrib/wpa_supplicant/examples/wpa2-eap-ccmp.conf b/contrib/wpa_supplicant/examples/wpa2-eap-ccmp.conf deleted file mode 100644 index d7a64d87b254..000000000000 --- a/contrib/wpa_supplicant/examples/wpa2-eap-ccmp.conf +++ /dev/null @@ -1,15 +0,0 @@ -# WPA2-EAP/CCMP using EAP-TLS - -ctrl_interface=/var/run/wpa_supplicant - -network={ - ssid="example wpa2-eap network" - key_mgmt=WPA-EAP - proto=WPA2 - pairwise=CCMP - group=CCMP - eap=TLS - ca_cert="/etc/cert/ca.pem" - private_key="/etc/cert/user.p12" - private_key_passwd="PKCS#12 passhrase" -} diff --git a/contrib/wpa_supplicant/hostapd.h b/contrib/wpa_supplicant/hostapd.h deleted file mode 100644 index 5ae9c8cc4f9e..000000000000 --- a/contrib/wpa_supplicant/hostapd.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef HOSTAPD_H -#define HOSTAPD_H - -/* - * Minimal version of hostapd header files for eapol_test to build - * radius_client.c. - */ - -#include "common.h" - -void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level, - char *fmt, ...) PRINTF_FORMAT(5, 6); - -struct hostapd_ip_addr; - -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); - -enum { - HOSTAPD_LEVEL_DEBUG_VERBOSE = 0, - HOSTAPD_LEVEL_DEBUG = 1, - HOSTAPD_LEVEL_INFO = 2, - HOSTAPD_LEVEL_NOTICE = 3, - HOSTAPD_LEVEL_WARNING = 4 -}; - -#ifndef BIT -#define BIT(n) (1 << (n)) -#endif - -#define HOSTAPD_MODULE_IEEE80211 BIT(0) -#define HOSTAPD_MODULE_IEEE8021X BIT(1) -#define HOSTAPD_MODULE_RADIUS BIT(2) -#define HOSTAPD_MODULE_WPA BIT(3) -#define HOSTAPD_MODULE_DRIVER BIT(4) -#define HOSTAPD_MODULE_IAPP BIT(5) - -#endif /* HOSTAPD_H */ diff --git a/contrib/wpa_supplicant/includes.h b/contrib/wpa_supplicant/includes.h deleted file mode 100644 index 84308c3a37a2..000000000000 --- a/contrib/wpa_supplicant/includes.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * wpa_supplicant/hostapd - Default include files - * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 #ifdefs 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 <stdlib.h> -#include <stdio.h> -#include <stdarg.h> -#include <string.h> -#ifndef _WIN32_WCE -#ifndef CONFIG_TI_COMPILER -#include <signal.h> -#include <sys/types.h> -#endif /* CONFIG_TI_COMPILER */ -#include <errno.h> -#endif /* _WIN32_WCE */ -#include <ctype.h> -#include <time.h> - -#ifndef CONFIG_TI_COMPILER -#ifndef _MSC_VER -#include <unistd.h> -#endif /* _MSC_VER */ -#endif /* CONFIG_TI_COMPILER */ - -#ifndef CONFIG_NATIVE_WINDOWS -#ifndef CONFIG_TI_COMPILER -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#ifndef __vxworks -#include <sys/uio.h> -#include <sys/time.h> -#endif /* __vxworks */ -#endif /* CONFIG_TI_COMPILER */ -#endif /* CONFIG_NATIVE_WINDOWS */ - -#endif /* INCLUDES_H */ diff --git a/contrib/wpa_supplicant/l2_packet.h b/contrib/wpa_supplicant/l2_packet.h deleted file mode 100644 index 540f0a116b56..000000000000 --- a/contrib/wpa_supplicant/l2_packet.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * WPA Supplicant - Layer2 packet interface definition - * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 - -#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] -#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" - -#ifndef ETH_P_EAPOL -#define ETH_P_EAPOL 0x888e -#endif - -#ifndef ETH_P_RSN_PREAUTH -#define ETH_P_RSN_PREAUTH 0x88c7 -#endif - -/** - * 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]; - u16 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/contrib/wpa_supplicant/libtommath.c b/contrib/wpa_supplicant/libtommath.c deleted file mode 100644 index b637707f31a8..000000000000 --- a/contrib/wpa_supplicant/libtommath.c +++ /dev/null @@ -1,2370 +0,0 @@ -/* - * Minimal code for RSA support from LibTomMath 0.3.9 - * http://math.libtomcrypt.com/ - * http://math.libtomcrypt.com/files/ltm-0.39.tar.bz2 - * This library was released in public domain by Tom St Denis. - * - * The combination in this file is not using many of the optimized algorithms - * (e.g., Montgomery reduction) and is considerable slower than the LibTomMath - * with its default of SC_RSA_1 settins. 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. However, it is likely worth the - * effort to use the full library with SC_RSA_1 instead of this minimized copy. - * Including the optimized algorithms may increase the size requirements by - * 15 kB or so (measured with x86 build). - * - * 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 */ - - -/* 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); - -static int mp_init_multi(mp_int *mp, ...); -static void mp_clear_multi(mp_int *mp, ...); -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); -static int mp_div_2(mp_int * a, mp_int * b); -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); -static int mp_invmod(mp_int * a, mp_int * b, mp_int * c); -static int mp_abs(mp_int * a, mp_int * b); -static int mp_invmod_slow(mp_int * a, mp_int * b, mp_int * c); -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); - - - -/* functions from bn_<func name>.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; - - /* 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 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 - } - -/* 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) { - dr = 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; - } -} - - -/* 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; -} - - -/* 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)); -} - - -/* 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; -} - - -/* 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; -} - - -/* 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; -} - - -/* 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; -} - - -/* 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; -} - - -/* 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; -} - - -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. */ -} - - -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); -} - - -/* 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; -} - - -/* 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; -} - - -#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; -} diff --git a/contrib/wpa_supplicant/main.c b/contrib/wpa_supplicant/main.c deleted file mode 100644 index aaef8220d1f6..000000000000 --- a/contrib/wpa_supplicant/main.c +++ /dev/null @@ -1,291 +0,0 @@ -/* - * WPA Supplicant / main() function for UNIX like OSes and MinGW - * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * $FreeBSD$ - */ - -#include "includes.h" -#ifdef __linux__ -#include <fcntl.h> -#endif /* __linux__ */ - -#include "common.h" -#include "wpa_supplicant_i.h" - - -extern const char *wpa_supplicant_version; -extern const char *wpa_supplicant_license; -#ifndef CONFIG_NO_STDOUT_DEBUG -extern const char *wpa_supplicant_full_license1; -extern const char *wpa_supplicant_full_license2; -extern const char *wpa_supplicant_full_license3; -extern const char *wpa_supplicant_full_license4; -extern const char *wpa_supplicant_full_license5; -#endif /* CONFIG_NO_STDOUT_DEBUG */ - -extern struct wpa_driver_ops *wpa_supplicant_drivers[]; - - -static void usage(void) -{ - int i; - printf("%s\n\n%s\n" - "usage:\n" - " wpa_supplicant [-BddhKLqqstuvwW] [-P<pid file>] " - "[-g<global ctrl>] \\\n" - " -i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] " - "[-p<driver_param>] \\\n" - " [-b<br_ifname>] [-f<debug file>] \\\n" - " [-N -i<ifname> -c<conf> [-C<ctrl>] " - "[-D<driver>] \\\n" - " [-p<driver_param>] [-b<br_ifname>] ...]\n" - "\n" - "drivers:\n", - wpa_supplicant_version, wpa_supplicant_license); - - for (i = 0; wpa_supplicant_drivers[i]; i++) { - printf(" %s = %s\n", - wpa_supplicant_drivers[i]->name, - wpa_supplicant_drivers[i]->desc); - } - -#ifndef CONFIG_NO_STDOUT_DEBUG - printf("options:\n" - " -b = optional bridge interface name\n" - " -B = run daemon in the background\n" - " -c = Configuration file\n" - " -C = ctrl_interface parameter (only used if -c is not)\n" - " -i = interface name\n" - " -d = increase debugging verbosity (-dd even more)\n" - " -D = driver name\n" -#ifdef CONFIG_DEBUG_FILE - " -f = log output to debug file instead of stdout\n" -#endif /* CONFIG_DEBUG_FILE */ - " -g = global ctrl_interface\n" - " -K = include keys (passwords, etc.) in debug output\n" - " -t = include timestamp in debug messages\n" - " -h = show this help text\n" - " -L = show license (GPL and BSD)\n"); - printf(" -p = driver parameters\n" - " -P = PID file\n" - " -q = decrease debugging verbosity (-qq even less)\n" -#ifdef CONFIG_DEBUG_SYSLOG - " -s = log output to syslog instead of stdout\n" -#endif /* CONFIG_DEBUG_SYSLOG */ -#ifdef CONFIG_CTRL_IFACE_DBUS - " -u = enable DBus control interface\n" -#endif /* CONFIG_CTRL_IFACE_DBUS */ - " -v = show version\n" - " -w = wait for interface to be added, if needed\n" - " -W = wait for a control interface monitor before starting\n" - " -N = start describing new interface\n"); - - printf("example:\n" - " wpa_supplicant -Dbsd -iwlan0 -c/etc/wpa_supplicant.conf\n"); -#endif /* CONFIG_NO_STDOUT_DEBUG */ -} - - -static void license(void) -{ -#ifndef CONFIG_NO_STDOUT_DEBUG - printf("%s\n\n%s%s%s%s%s\n", - wpa_supplicant_version, - wpa_supplicant_full_license1, - wpa_supplicant_full_license2, - wpa_supplicant_full_license3, - wpa_supplicant_full_license4, - wpa_supplicant_full_license5); -#endif /* CONFIG_NO_STDOUT_DEBUG */ -} - - -static void wpa_supplicant_fd_workaround(void) -{ -#ifdef __linux__ - int s, i; - /* When started from pcmcia-cs scripts, wpa_supplicant might start with - * fd 0, 1, and 2 closed. This will cause some issues because many - * places in wpa_supplicant are still printing out to stdout. As a - * workaround, make sure that fd's 0, 1, and 2 are not used for other - * sockets. */ - for (i = 0; i < 3; i++) { - s = open("/dev/null", O_RDWR); - if (s > 2) { - close(s); - break; - } - } -#endif /* __linux__ */ -} - - -int main(int argc, char *argv[]) -{ - int c, i; - struct wpa_interface *ifaces, *iface; - int iface_count, exitcode = -1; - struct wpa_params params; - struct wpa_global *global; - - if (os_program_init()) - return -1; - - os_memset(¶ms, 0, sizeof(params)); - params.wpa_debug_level = MSG_INFO; - - iface = ifaces = os_zalloc(sizeof(struct wpa_interface)); - if (ifaces == NULL) - return -1; - iface_count = 1; - - wpa_supplicant_fd_workaround(); - - for (;;) { - c = getopt(argc, argv, "b:Bc:C:D:df:g:hi:KLNp:P:qstuvwW"); - if (c < 0) - break; - switch (c) { - case 'b': - iface->bridge_ifname = optarg; - break; - case 'B': - params.daemonize++; - break; - case 'c': - iface->confname = optarg; - break; - case 'C': - iface->ctrl_interface = optarg; - break; - case 'D': - iface->driver = optarg; - break; - case 'd': -#ifdef CONFIG_NO_STDOUT_DEBUG - printf("Debugging disabled with " - "CONFIG_NO_STDOUT_DEBUG=y build time " - "option.\n"); - goto out; -#else /* CONFIG_NO_STDOUT_DEBUG */ - params.wpa_debug_level--; - break; -#endif /* CONFIG_NO_STDOUT_DEBUG */ -#ifdef CONFIG_DEBUG_FILE - case 'f': - params.wpa_debug_file_path = optarg; - break; -#endif /* CONFIG_DEBUG_FILE */ - case 'g': - params.ctrl_interface = optarg; - break; - case 'h': - usage(); - exitcode = 0; - goto out; - case 'i': - iface->ifname = optarg; - break; - case 'K': - params.wpa_debug_show_keys++; - break; - case 'L': - license(); - exitcode = 0; - goto out; - case 'p': - iface->driver_param = optarg; - break; - case 'P': - os_free(params.pid_file); - params.pid_file = os_rel2abs_path(optarg); - break; - case 'q': - params.wpa_debug_level++; - break; -#ifdef CONFIG_DEBUG_SYSLOG - case 's': - params.wpa_debug_syslog++; - break; -#endif /* CONFIG_DEBUG_SYSLOG */ - case 't': - params.wpa_debug_timestamp++; - break; -#ifdef CONFIG_CTRL_IFACE_DBUS - case 'u': - params.dbus_ctrl_interface = 1; - break; -#endif /* CONFIG_CTRL_IFACE_DBUS */ - case 'v': - printf("%s\n", wpa_supplicant_version); - exitcode = 0; - goto out; - case 'w': - params.wait_for_interface++; - break; - case 'W': - params.wait_for_monitor++; - break; - case 'N': - iface_count++; - iface = os_realloc(ifaces, iface_count * - sizeof(struct wpa_interface)); - if (iface == NULL) - goto out; - ifaces = iface; - iface = &ifaces[iface_count - 1]; - os_memset(iface, 0, sizeof(*iface)); - break; - default: - usage(); - exitcode = 0; - goto out; - } - } - - exitcode = 0; - global = wpa_supplicant_init(¶ms); - if (global == NULL) { - printf("Failed to initialize wpa_supplicant\n"); - exitcode = -1; - goto out; - } - - for (i = 0; exitcode == 0 && i < iface_count; i++) { - if ((ifaces[i].confname == NULL && - ifaces[i].ctrl_interface == NULL) || - ifaces[i].ifname == NULL) { - if (iface_count == 1 && (params.ctrl_interface || - params.dbus_ctrl_interface)) - break; - usage(); - exitcode = -1; - break; - } - if (wpa_supplicant_add_iface(global, &ifaces[i]) == NULL) - exitcode = -1; - } - - if (exitcode == 0) - exitcode = wpa_supplicant_run(global); - - wpa_supplicant_deinit(global); - -out: - os_free(ifaces); - os_free(params.pid_file); - - os_program_deinit(); - - return exitcode; -} diff --git a/contrib/wpa_supplicant/md4.c b/contrib/wpa_supplicant/md4.c deleted file mode 100644 index 41c84a3a7b5d..000000000000 --- a/contrib/wpa_supplicant/md4.c +++ /dev/null @@ -1,282 +0,0 @@ -/* - * MD4 hash implementation - * Copyright (c) 2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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" - - -#ifdef INTERNAL_MD4 - -#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); - - -void 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); -} - - -/* ===== 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<<s | 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 ===== */ - -#endif /* INTERNAL_MD4 */ diff --git a/contrib/wpa_supplicant/md5.c b/contrib/wpa_supplicant/md5.c deleted file mode 100644 index a7db7aa9a771..000000000000 --- a/contrib/wpa_supplicant/md5.c +++ /dev/null @@ -1,394 +0,0 @@ -/* - * MD5 hash implementation and interface functions - * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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) - */ -void 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; - } - - /* if key is longer than 64 bytes reset it to key = MD5(key) */ - if (key_len > 64) { - md5_vector(1, &key, &key_len, tk); - 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]; - } - md5_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 MD5 */ - _addr[0] = k_pad; - _len[0] = 64; - _addr[1] = mac; - _len[1] = MD5_MAC_LEN; - 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) - */ -void hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len, - u8 *mac) -{ - hmac_md5_vector(key, key_len, 1, &data, &data_len, mac); -} - - -#ifdef INTERNAL_MD5 - -struct MD5Context { - u32 buf[4]; - u32 bits[2]; - u8 in[64]; -}; - -#ifndef CONFIG_CRYPTO_INTERNAL -static void MD5Init(struct MD5Context *context); -static void MD5Update(struct MD5Context *context, unsigned char const *buf, - unsigned len); -static void MD5Final(unsigned char digest[16], struct MD5Context *context); -#endif /* CONFIG_CRYPTO_INTERNAL */ -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 - */ -void 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); -} - - -/* ===== 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(ctx)); /* 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<<s | 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 ===== */ - -#endif /* INTERNAL_MD5 */ diff --git a/contrib/wpa_supplicant/md5.h b/contrib/wpa_supplicant/md5.h deleted file mode 100644 index e82f3969ed08..000000000000 --- a/contrib/wpa_supplicant/md5.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * MD5 hash implementation and interface functions - * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 - -void hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac); -void hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len, - u8 *mac); - -#ifdef CONFIG_CRYPTO_INTERNAL -struct MD5Context; - -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 /* CONFIG_CRYPTO_INTERNAL */ - -#endif /* MD5_H */ diff --git a/contrib/wpa_supplicant/mlme.c b/contrib/wpa_supplicant/mlme.c deleted file mode 100644 index e618e2abb7bd..000000000000 --- a/contrib/wpa_supplicant/mlme.c +++ /dev/null @@ -1,2896 +0,0 @@ -/* - * WPA Supplicant - Client mode MLME - * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi> - * Copyright (c) 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. - */ - -#include "includes.h" - -#include "common.h" -#include "eloop.h" -#include "config.h" -#include "wpa_supplicant.h" -#include "wpa_supplicant_i.h" -#include "wpa.h" -#include "os.h" -#include "l2_packet.h" -#include "driver.h" -#include "mlme.h" - - -/* Timeouts and intervals in milliseconds */ -#define IEEE80211_AUTH_TIMEOUT (200) -#define IEEE80211_AUTH_MAX_TRIES 3 -#define IEEE80211_ASSOC_TIMEOUT (200) -#define IEEE80211_ASSOC_MAX_TRIES 3 -#define IEEE80211_MONITORING_INTERVAL (2000) -#define IEEE80211_PROBE_INTERVAL (60000) -#define IEEE80211_RETRY_AUTH_INTERVAL (1000) -#define IEEE80211_SCAN_INTERVAL (2000) -#define IEEE80211_SCAN_INTERVAL_SLOW (15000) -#define IEEE80211_IBSS_JOIN_TIMEOUT (20000) - -#define IEEE80211_PROBE_DELAY (33) -#define IEEE80211_CHANNEL_TIME (33) -#define IEEE80211_PASSIVE_CHANNEL_TIME (200) -#define IEEE80211_SCAN_RESULT_EXPIRE (10000) -#define IEEE80211_IBSS_MERGE_INTERVAL (30000) -#define IEEE80211_IBSS_INACTIVITY_LIMIT (60000) - -#define IEEE80211_IBSS_MAX_STA_ENTRIES 128 - - -/* 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 as part fo 11h - starts */ -#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 as part fo 11h - ends */ -#define WLAN_EID_ERP_INFO 42 -#define WLAN_EID_RSN 48 -#define WLAN_EID_EXT_SUPP_RATES 50 -#define WLAN_EID_VENDOR_SPECIFIC 221 - - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -struct ieee80211_mgmt { - u16 frame_control; - u16 duration; - u8 da[6]; - u8 sa[6]; - u8 bssid[6]; - u16 seq_ctrl; - union { - struct { - u16 auth_alg; - u16 auth_transaction; - u16 status_code; - /* possibly followed by Challenge text */ - u8 variable[0]; - } STRUCT_PACKED auth; - struct { - u16 reason_code; - } STRUCT_PACKED deauth; - struct { - u16 capab_info; - u16 listen_interval; - /* followed by SSID and Supported rates */ - u8 variable[0]; - } STRUCT_PACKED assoc_req; - struct { - u16 capab_info; - u16 status_code; - u16 aid; - /* followed by Supported rates */ - u8 variable[0]; - } STRUCT_PACKED assoc_resp, reassoc_resp; - struct { - u16 capab_info; - u16 listen_interval; - u8 current_ap[6]; - /* followed by SSID and Supported rates */ - u8 variable[0]; - } STRUCT_PACKED reassoc_req; - struct { - u16 reason_code; - } STRUCT_PACKED disassoc; - struct { - u8 timestamp[8]; - u16 beacon_int; - u16 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]; - u16 beacon_int; - u16 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 wme_action; - struct{ - u8 action_code; - u8 element_id; - u8 length; - u8 switch_mode; - u8 new_chan; - u8 switch_count; - } __attribute__((packed)) chan_switch; - } u; - } STRUCT_PACKED action; - } u; -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - -/* Authentication algorithms */ -#define WLAN_AUTH_OPEN 0 -#define WLAN_AUTH_SHARED_KEY 1 -#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) -/* 802.11h */ -#define WLAN_CAPABILITY_SPECTRUM_MGMT BIT(8) -#define WLAN_CAPABILITY_SHORT_SLOT_TIME BIT(10) -#define WLAN_CAPABILITY_DSSS_OFDM BIT(13) - -/* Status codes */ -#define WLAN_STATUS_SUCCESS 0 -#define WLAN_STATUS_UNSPECIFIED_FAILURE 1 -#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 -/* 802.11b */ -#define WLAN_STATUS_ASSOC_DENIED_NOSHORT 19 -#define WLAN_STATUS_ASSOC_DENIED_NOPBCC 20 -#define WLAN_STATUS_ASSOC_DENIED_NOAGILITY 21 -/* 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 -/* 802.11g */ -#define WLAN_STATUS_ASSOC_DENOED_NO_SHORT_SLOT_TIME 25 -#define WLAN_STATUS_ASSOC_DENOED_NO_ER_PBCC 26 -#define WLAN_STATUS_ASSOC_DENOED_NO_DSSS_OFDM 27 - - -/* Reason codes */ -#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 -/* 802.11h */ -#define WLAN_REASON_PWR_CAPABILITY_NOT_VALID 10 -#define WLAN_REASON_SUPPORTED_CHANNEL_NOT_VALID 11 - -#define WLAN_REASON_MIC_FAILURE 14 - - -#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 IEEE80211_FC(type, stype) host_to_le16((type << 2) | (stype << 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 - - -#define ERP_INFO_USE_PROTECTION BIT(1) - - -struct ieee80211_sta_bss { - struct ieee80211_sta_bss *next; - struct ieee80211_sta_bss *hnext; - - u8 bssid[ETH_ALEN]; - u8 ssid[MAX_SSID_LEN]; - size_t ssid_len; - u16 capability; /* host byte order */ - int hw_mode; - int channel; - int freq; - int rssi; - u8 *wpa_ie; - size_t wpa_ie_len; - u8 *rsn_ie; - size_t rsn_ie_len; - u8 *wmm_ie; - size_t wmm_ie_len; -#define IEEE80211_MAX_SUPP_RATES 32 - u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; - size_t supp_rates_len; - int beacon_int; - u64 timestamp; - - int probe_resp; - struct os_time last_update; -}; - - -static void ieee80211_send_probe_req(struct wpa_supplicant *wpa_s, - const u8 *dst, - const u8 *ssid, size_t ssid_len); -static struct ieee80211_sta_bss * -ieee80211_bss_get(struct wpa_supplicant *wpa_s, const u8 *bssid); -static int ieee80211_sta_find_ibss(struct wpa_supplicant *wpa_s); -static int ieee80211_sta_wep_configured(struct wpa_supplicant *wpa_s); -static void ieee80211_sta_timer(void *eloop_ctx, void *timeout_ctx); -static void ieee80211_sta_scan_timer(void *eloop_ctx, void *timeout_ctx); - - -/* Parsed Information Elements */ -struct ieee802_11_elems { - u8 *ssid; - u8 ssid_len; - u8 *supp_rates; - u8 supp_rates_len; - u8 *fh_params; - u8 fh_params_len; - u8 *ds_params; - u8 ds_params_len; - u8 *cf_params; - u8 cf_params_len; - u8 *tim; - u8 tim_len; - u8 *ibss_params; - u8 ibss_params_len; - u8 *challenge; - u8 challenge_len; - u8 *wpa; - u8 wpa_len; - u8 *rsn; - u8 rsn_len; - u8 *erp_info; - u8 erp_info_len; - u8 *ext_supp_rates; - u8 ext_supp_rates_len; - u8 *wmm_info; - u8 wmm_info_len; - u8 *wmm_param; - u8 wmm_param_len; -}; - -typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes; - - -static ParseRes ieee802_11_parse_elems(u8 *start, size_t len, - struct ieee802_11_elems *elems) -{ - size_t left = len; - 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 0 - wpa_printf(MSG_MSGDUMP, "MLME: IEEE 802.11 element " - "parse failed (id=%d elen=%d left=%d)", - id, elen, left); -#endif - 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_VENDOR_SPECIFIC: - if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 && - pos[2] == 0xf2) { - /* Microsoft OUI (00:50:F2) */ - if (pos[3] == 1) { - /* OUI Type 1 - WPA IE */ - elems->wpa = pos; - elems->wpa_len = elen; - } else if (elen >= 5 && pos[3] == 2) { - if (pos[4] == 0) { - elems->wmm_info = pos; - elems->wmm_info_len = elen; - } else if (pos[4] == 1) { - elems->wmm_param = pos; - elems->wmm_param_len = elen; - } - } - } - break; - case WLAN_EID_RSN: - elems->rsn = pos; - elems->rsn_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; - default: -#if 0 - wpa_printf(MSG_MSGDUMP "MLME: IEEE 802.11 element " - "parse ignored unknown element (id=%d " - "elen=%d)", id, elen); -#endif - unknown++; - break; - } - - left -= elen; - pos += elen; - } - - if (left) - return ParseFailed; - - return unknown ? ParseUnknown : ParseOK; -} - - -static int ieee80211_sta_set_channel(struct wpa_supplicant *wpa_s, - wpa_hw_mode phymode, int chan, - int freq) -{ - size_t i; - struct wpa_hw_modes *mode; - - for (i = 0; i < wpa_s->mlme.num_modes; i++) { - mode = &wpa_s->mlme.modes[i]; - if (mode->mode == phymode) { - wpa_s->mlme.curr_rates = mode->rates; - wpa_s->mlme.num_curr_rates = mode->num_rates; - break; - } - } - - return wpa_drv_set_channel(wpa_s, phymode, chan, freq); -} - - - -#if 0 /* FIX */ -static int ecw2cw(int ecw) -{ - int cw = 1; - while (ecw > 0) { - cw <<= 1; - ecw--; - } - return cw - 1; -} -#endif - - -static void ieee80211_sta_wmm_params(struct wpa_supplicant *wpa_s, - u8 *wmm_param, size_t wmm_param_len) -{ - size_t left; - int count; - u8 *pos; - - if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1) - return; - count = wmm_param[6] & 0x0f; - if (count == wpa_s->mlme.wmm_last_param_set) - return; - wpa_s->mlme.wmm_last_param_set = count; - - pos = wmm_param + 8; - left = wmm_param_len - 8; - -#if 0 /* FIX */ - wmm_acm = 0; - for (; left >= 4; left -= 4, pos += 4) { - int aci = (pos[0] >> 5) & 0x03; - int acm = (pos[0] >> 4) & 0x01; - int queue; - - switch (aci) { - case 1: - queue = IEEE80211_TX_QUEUE_DATA3; - if (acm) - wmm_acm |= BIT(1) | BIT(2); - break; - case 2: - queue = IEEE80211_TX_QUEUE_DATA1; - if (acm) - wmm_acm |= BIT(4) | BIT(5); - break; - case 3: - queue = IEEE80211_TX_QUEUE_DATA0; - if (acm) - wmm_acm |= BIT(6) | BIT(7); - break; - case 0: - default: - queue = IEEE80211_TX_QUEUE_DATA2; - if (acm) - wpa_s->mlme.wmm_acm |= BIT(0) | BIT(3); - break; - } - - params.aifs = pos[0] & 0x0f; - params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4); - params.cw_min = ecw2cw(pos[1] & 0x0f); - /* TXOP is in units of 32 usec; burst_time in 0.1 ms */ - params.burst_time = (pos[2] | (pos[3] << 8)) * 32 / 100; - wpa_printf(MSG_DEBUG, "MLME: WMM queue=%d aci=%d acm=%d " - "aifs=%d cWmin=%d cWmax=%d burst=%d", - queue, aci, acm, params.aifs, params.cw_min, - params.cw_max, params.burst_time); - /* TODO: handle ACM (block TX, fallback to next lowest allowed - * AC for now) */ - if (local->hw->conf_tx(local->mdev, queue, ¶ms)) { - wpa_printf(MSG_DEBUG, "MLME: failed to set TX queue " - "parameters for queue %d", queue); - } - } -#endif -} - - -static void ieee80211_set_associated(struct wpa_supplicant *wpa_s, int assoc) -{ - if (wpa_s->mlme.associated == assoc) - return; - - wpa_s->mlme.associated = assoc; - - if (assoc) { - union wpa_event_data data; - os_memset(&data, 0, sizeof(data)); - wpa_s->mlme.prev_bssid_set = 1; - os_memcpy(wpa_s->mlme.prev_bssid, wpa_s->bssid, ETH_ALEN); - data.assoc_info.req_ies = wpa_s->mlme.assocreq_ies; - data.assoc_info.req_ies_len = wpa_s->mlme.assocreq_ies_len; - data.assoc_info.resp_ies = wpa_s->mlme.assocresp_ies; - data.assoc_info.resp_ies_len = wpa_s->mlme.assocresp_ies_len; - wpa_supplicant_event(wpa_s, EVENT_ASSOC, &data); - } else { - wpa_supplicant_event(wpa_s, EVENT_DISASSOC, NULL); - } - os_get_time(&wpa_s->mlme.last_probe); -} - - -static void ieee80211_sta_tx(struct wpa_supplicant *wpa_s, const u8 *buf, - size_t len) -{ - wpa_drv_send_mlme(wpa_s, buf, len); -} - - -static void ieee80211_send_auth(struct wpa_supplicant *wpa_s, - int transaction, u8 *extra, size_t extra_len, - int encrypt) -{ - u8 *buf; - size_t len; - struct ieee80211_mgmt *mgmt; - - buf = os_malloc(sizeof(*mgmt) + 6 + extra_len); - if (buf == NULL) { - wpa_printf(MSG_DEBUG, "MLME: failed to allocate buffer for " - "auth frame"); - return; - } - - mgmt = (struct ieee80211_mgmt *) buf; - len = 24 + 6; - os_memset(mgmt, 0, 24 + 6); - mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_AUTH); - if (encrypt) - mgmt->frame_control |= host_to_le16(WLAN_FC_ISWEP); - os_memcpy(mgmt->da, wpa_s->bssid, ETH_ALEN); - os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN); - os_memcpy(mgmt->bssid, wpa_s->bssid, ETH_ALEN); - mgmt->u.auth.auth_alg = host_to_le16(wpa_s->mlme.auth_alg); - mgmt->u.auth.auth_transaction = host_to_le16(transaction); - wpa_s->mlme.auth_transaction = transaction + 1; - mgmt->u.auth.status_code = host_to_le16(0); - if (extra) { - os_memcpy(buf + len, extra, extra_len); - len += extra_len; - } - - ieee80211_sta_tx(wpa_s, buf, len); - os_free(buf); -} - - -static void ieee80211_reschedule_timer(struct wpa_supplicant *wpa_s, int ms) -{ - eloop_cancel_timeout(ieee80211_sta_timer, wpa_s, NULL); - eloop_register_timeout(ms / 1000, 1000 * (ms % 1000), - ieee80211_sta_timer, wpa_s, NULL); -} - - -static void ieee80211_authenticate(struct wpa_supplicant *wpa_s) -{ - wpa_s->mlme.auth_tries++; - if (wpa_s->mlme.auth_tries > IEEE80211_AUTH_MAX_TRIES) { - wpa_printf(MSG_DEBUG, "MLME: authentication with AP " MACSTR - " timed out", MAC2STR(wpa_s->bssid)); - return; - } - - wpa_s->mlme.state = IEEE80211_AUTHENTICATE; - wpa_printf(MSG_DEBUG, "MLME: authenticate with AP " MACSTR, - MAC2STR(wpa_s->bssid)); - - ieee80211_send_auth(wpa_s, 1, NULL, 0, 0); - - ieee80211_reschedule_timer(wpa_s, IEEE80211_AUTH_TIMEOUT); -} - - -static void ieee80211_send_assoc(struct wpa_supplicant *wpa_s) -{ - struct ieee80211_mgmt *mgmt; - u8 *pos, *ies, *buf; - int i, len; - u16 capab; - struct ieee80211_sta_bss *bss; - int wmm = 0; - size_t blen; - - if (wpa_s->mlme.curr_rates == NULL) { - wpa_printf(MSG_DEBUG, "MLME: curr_rates not set for assoc"); - return; - } - - buf = os_malloc(sizeof(*mgmt) + 200 + wpa_s->mlme.extra_ie_len + - wpa_s->mlme.ssid_len); - if (buf == NULL) { - wpa_printf(MSG_DEBUG, "MLME: failed to allocate buffer for " - "assoc frame"); - return; - } - blen = 0; - - capab = wpa_s->mlme.capab; - if (wpa_s->mlme.phymode == WPA_MODE_IEEE80211G) { - capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME | - WLAN_CAPABILITY_SHORT_PREAMBLE; - } - bss = ieee80211_bss_get(wpa_s, wpa_s->bssid); - if (bss) { - if (bss->capability & WLAN_CAPABILITY_PRIVACY) - capab |= WLAN_CAPABILITY_PRIVACY; - if (bss->wmm_ie) { - wmm = 1; - } - } - - mgmt = (struct ieee80211_mgmt *) buf; - blen += 24; - os_memset(mgmt, 0, 24); - os_memcpy(mgmt->da, wpa_s->bssid, ETH_ALEN); - os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN); - os_memcpy(mgmt->bssid, wpa_s->bssid, ETH_ALEN); - - if (wpa_s->mlme.prev_bssid_set) { - blen += 10; - mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_REASSOC_REQ); - mgmt->u.reassoc_req.capab_info = host_to_le16(capab); - mgmt->u.reassoc_req.listen_interval = host_to_le16(1); - os_memcpy(mgmt->u.reassoc_req.current_ap, - wpa_s->mlme.prev_bssid, - ETH_ALEN); - } else { - blen += 4; - mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_ASSOC_REQ); - mgmt->u.assoc_req.capab_info = host_to_le16(capab); - mgmt->u.assoc_req.listen_interval = host_to_le16(1); - } - - /* SSID */ - ies = pos = buf + blen; - blen += 2 + wpa_s->mlme.ssid_len; - *pos++ = WLAN_EID_SSID; - *pos++ = wpa_s->mlme.ssid_len; - os_memcpy(pos, wpa_s->mlme.ssid, wpa_s->mlme.ssid_len); - - len = wpa_s->mlme.num_curr_rates; - if (len > 8) - len = 8; - pos = buf + blen; - blen += len + 2; - *pos++ = WLAN_EID_SUPP_RATES; - *pos++ = len; - for (i = 0; i < len; i++) { - int rate = wpa_s->mlme.curr_rates[i].rate; - *pos++ = (u8) (rate / 5); - } - - if (wpa_s->mlme.num_curr_rates > len) { - pos = buf + blen; - blen += wpa_s->mlme.num_curr_rates - len + 2; - *pos++ = WLAN_EID_EXT_SUPP_RATES; - *pos++ = wpa_s->mlme.num_curr_rates - len; - for (i = len; i < wpa_s->mlme.num_curr_rates; i++) { - int rate = wpa_s->mlme.curr_rates[i].rate; - *pos++ = (u8) (rate / 5); - } - } - - if (wpa_s->mlme.extra_ie) { - pos = buf + blen; - blen += wpa_s->mlme.extra_ie_len; - os_memcpy(pos, wpa_s->mlme.extra_ie, wpa_s->mlme.extra_ie_len); - } - - if (wmm && wpa_s->mlme.wmm_enabled) { - pos = buf + blen; - blen += 9; - *pos++ = WLAN_EID_VENDOR_SPECIFIC; - *pos++ = 7; /* len */ - *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */ - *pos++ = 0x50; - *pos++ = 0xf2; - *pos++ = 2; /* WME */ - *pos++ = 0; /* WME info */ - *pos++ = 1; /* WME ver */ - *pos++ = 0; - } - - os_free(wpa_s->mlme.assocreq_ies); - wpa_s->mlme.assocreq_ies_len = (buf + blen) - ies; - wpa_s->mlme.assocreq_ies = os_malloc(wpa_s->mlme.assocreq_ies_len); - if (wpa_s->mlme.assocreq_ies) { - os_memcpy(wpa_s->mlme.assocreq_ies, ies, - wpa_s->mlme.assocreq_ies_len); - } - - ieee80211_sta_tx(wpa_s, buf, blen); - os_free(buf); -} - - -static void ieee80211_send_deauth(struct wpa_supplicant *wpa_s, u16 reason) -{ - u8 *buf; - size_t len; - struct ieee80211_mgmt *mgmt; - - buf = os_zalloc(sizeof(*mgmt)); - if (buf == NULL) { - wpa_printf(MSG_DEBUG, "MLME: failed to allocate buffer for " - "deauth frame"); - return; - } - - mgmt = (struct ieee80211_mgmt *) buf; - len = 24; - os_memcpy(mgmt->da, wpa_s->bssid, ETH_ALEN); - os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN); - os_memcpy(mgmt->bssid, wpa_s->bssid, ETH_ALEN); - mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_DEAUTH); - len += 2; - mgmt->u.deauth.reason_code = host_to_le16(reason); - - ieee80211_sta_tx(wpa_s, buf, len); - os_free(buf); -} - - -static void ieee80211_send_disassoc(struct wpa_supplicant *wpa_s, u16 reason) -{ - u8 *buf; - size_t len; - struct ieee80211_mgmt *mgmt; - - buf = os_zalloc(sizeof(*mgmt)); - if (buf == NULL) { - wpa_printf(MSG_DEBUG, "MLME: failed to allocate buffer for " - "disassoc frame"); - return; - } - - mgmt = (struct ieee80211_mgmt *) buf; - len = 24; - os_memcpy(mgmt->da, wpa_s->bssid, ETH_ALEN); - os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN); - os_memcpy(mgmt->bssid, wpa_s->bssid, ETH_ALEN); - mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_DISASSOC); - len += 2; - mgmt->u.disassoc.reason_code = host_to_le16(reason); - - ieee80211_sta_tx(wpa_s, buf, len); - os_free(buf); -} - - -static int ieee80211_privacy_mismatch(struct wpa_supplicant *wpa_s) -{ - struct ieee80211_sta_bss *bss; - int res = 0; - - if (wpa_s->mlme.mixed_cell || - wpa_s->mlme.key_mgmt != KEY_MGMT_NONE) - return 0; - - bss = ieee80211_bss_get(wpa_s, wpa_s->bssid); - if (bss == NULL) - return 0; - - if (ieee80211_sta_wep_configured(wpa_s) != - !!(bss->capability & WLAN_CAPABILITY_PRIVACY)) - res = 1; - - return res; -} - - -static void ieee80211_associate(struct wpa_supplicant *wpa_s) -{ - wpa_s->mlme.assoc_tries++; - if (wpa_s->mlme.assoc_tries > IEEE80211_ASSOC_MAX_TRIES) { - wpa_printf(MSG_DEBUG, "MLME: association with AP " MACSTR - " timed out", MAC2STR(wpa_s->bssid)); - return; - } - - wpa_s->mlme.state = IEEE80211_ASSOCIATE; - wpa_printf(MSG_DEBUG, "MLME: associate with AP " MACSTR, - MAC2STR(wpa_s->bssid)); - if (ieee80211_privacy_mismatch(wpa_s)) { - wpa_printf(MSG_DEBUG, "MLME: mismatch in privacy " - "configuration and mixed-cell disabled - abort " - "association"); - return; - } - - ieee80211_send_assoc(wpa_s); - - ieee80211_reschedule_timer(wpa_s, IEEE80211_ASSOC_TIMEOUT); -} - - -static void ieee80211_associated(struct wpa_supplicant *wpa_s) -{ - int disassoc; - - /* TODO: start monitoring current AP signal quality and number of - * missed beacons. Scan other channels every now and then and search - * for better APs. */ - /* TODO: remove expired BSSes */ - - wpa_s->mlme.state = IEEE80211_ASSOCIATED; - -#if 0 /* FIX */ - sta = sta_info_get(local, wpa_s->bssid); - if (sta == NULL) { - wpa_printf(MSG_DEBUG "MLME: No STA entry for own AP " MACSTR, - MAC2STR(wpa_s->bssid)); - disassoc = 1; - } else { - disassoc = 0; - if (time_after(jiffies, - sta->last_rx + IEEE80211_MONITORING_INTERVAL)) { - if (wpa_s->mlme.probereq_poll) { - wpa_printf(MSG_DEBUG "MLME: No ProbeResp from " - "current AP " MACSTR " - assume " - "out of range", - MAC2STR(wpa_s->bssid)); - disassoc = 1; - } else { - ieee80211_send_probe_req( - wpa_s->bssid, - wpa_s->mlme.scan_ssid, - wpa_s->mlme.scan_ssid_len); - wpa_s->mlme.probereq_poll = 1; - } - } else { - wpa_s->mlme.probereq_poll = 0; - if (time_after(jiffies, wpa_s->mlme.last_probe + - IEEE80211_PROBE_INTERVAL)) { - wpa_s->mlme.last_probe = jiffies; - ieee80211_send_probe_req(wpa_s->bssid, - wpa_s->mlme.ssid, - wpa_s->mlme.ssid_len); - } - } - sta_info_release(local, sta); - } -#else - disassoc = 0; -#endif - if (disassoc) { - wpa_supplicant_event(wpa_s, EVENT_DISASSOC, NULL); - ieee80211_reschedule_timer(wpa_s, - IEEE80211_MONITORING_INTERVAL + - 30000); - } else { - ieee80211_reschedule_timer(wpa_s, - IEEE80211_MONITORING_INTERVAL); - } -} - - -static void ieee80211_send_probe_req(struct wpa_supplicant *wpa_s, - const u8 *dst, - const u8 *ssid, size_t ssid_len) -{ - u8 *buf; - size_t len; - struct ieee80211_mgmt *mgmt; - u8 *pos, *supp_rates; - u8 *esupp_rates = NULL; - int i; - - buf = os_malloc(sizeof(*mgmt) + 200); - if (buf == NULL) { - wpa_printf(MSG_DEBUG, "MLME: failed to allocate buffer for " - "probe request"); - return; - } - - mgmt = (struct ieee80211_mgmt *) buf; - len = 24; - os_memset(mgmt, 0, 24); - mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_PROBE_REQ); - os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN); - if (dst) { - os_memcpy(mgmt->da, dst, ETH_ALEN); - os_memcpy(mgmt->bssid, dst, ETH_ALEN); - } else { - os_memset(mgmt->da, 0xff, ETH_ALEN); - os_memset(mgmt->bssid, 0xff, ETH_ALEN); - } - pos = buf + len; - len += 2 + ssid_len; - *pos++ = WLAN_EID_SSID; - *pos++ = ssid_len; - os_memcpy(pos, ssid, ssid_len); - - supp_rates = buf + len; - len += 2; - supp_rates[0] = WLAN_EID_SUPP_RATES; - supp_rates[1] = 0; - for (i = 0; i < wpa_s->mlme.num_curr_rates; i++) { - struct wpa_rate_data *rate = &wpa_s->mlme.curr_rates[i]; - if (esupp_rates) { - pos = buf + len; - len++; - esupp_rates[1]++; - } else if (supp_rates[1] == 8) { - esupp_rates = pos; - esupp_rates[0] = WLAN_EID_EXT_SUPP_RATES; - esupp_rates[1] = 1; - pos = &esupp_rates[2]; - len += 3; - } else { - pos = buf + len; - len++; - supp_rates[1]++; - } - *pos = rate->rate / 5; - } - - ieee80211_sta_tx(wpa_s, buf, len); - os_free(buf); -} - - -static int ieee80211_sta_wep_configured(struct wpa_supplicant *wpa_s) -{ -#if 0 /* FIX */ - if (sdata == NULL || sdata->default_key == NULL || - sdata->default_key->alg != ALG_WEP) - return 0; - return 1; -#else - return 0; -#endif -} - - -static void ieee80211_auth_completed(struct wpa_supplicant *wpa_s) -{ - wpa_printf(MSG_DEBUG, "MLME: authenticated"); - wpa_s->mlme.authenticated = 1; - ieee80211_associate(wpa_s); -} - - -static void ieee80211_auth_challenge(struct wpa_supplicant *wpa_s, - struct ieee80211_mgmt *mgmt, - size_t len, - struct ieee80211_rx_status *rx_status) -{ - u8 *pos; - struct ieee802_11_elems elems; - - wpa_printf(MSG_DEBUG, "MLME: replying to auth challenge"); - pos = mgmt->u.auth.variable; - if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems) - == ParseFailed) { - wpa_printf(MSG_DEBUG, "MLME: failed to parse Auth(challenge)"); - return; - } - if (elems.challenge == NULL) { - wpa_printf(MSG_DEBUG, "MLME: no challenge IE in shared key " - "auth frame"); - return; - } - ieee80211_send_auth(wpa_s, 3, elems.challenge - 2, - elems.challenge_len + 2, 1); -} - - -static void ieee80211_rx_mgmt_auth(struct wpa_supplicant *wpa_s, - struct ieee80211_mgmt *mgmt, - size_t len, - struct ieee80211_rx_status *rx_status) -{ - struct wpa_ssid *ssid = wpa_s->current_ssid; - u16 auth_alg, auth_transaction, status_code; - int adhoc; - - adhoc = ssid && ssid->mode == 1; - - if (wpa_s->mlme.state != IEEE80211_AUTHENTICATE && !adhoc) { - wpa_printf(MSG_DEBUG, "MLME: authentication frame received " - "from " MACSTR ", but not in authenticate state - " - "ignored", MAC2STR(mgmt->sa)); - return; - } - - if (len < 24 + 6) { - wpa_printf(MSG_DEBUG, "MLME: too short (%lu) authentication " - "frame received from " MACSTR " - ignored", - (unsigned long) len, MAC2STR(mgmt->sa)); - return; - } - - if (!adhoc && os_memcmp(wpa_s->bssid, mgmt->sa, ETH_ALEN) != 0) { - wpa_printf(MSG_DEBUG, "MLME: authentication frame received " - "from unknown AP (SA=" MACSTR " BSSID=" MACSTR - ") - ignored", - MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid)); - return; - } - - if (adhoc && os_memcmp(wpa_s->bssid, mgmt->bssid, ETH_ALEN) != 0) { - wpa_printf(MSG_DEBUG, "MLME: authentication frame received " - "from unknown BSSID (SA=" MACSTR " BSSID=" MACSTR - ") - ignored", - MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid)); - 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); - - wpa_printf(MSG_DEBUG, "MLME: RX authentication from " MACSTR - " (alg=%d transaction=%d status=%d)", - MAC2STR(mgmt->sa), auth_alg, auth_transaction, status_code); - - if (adhoc) { - /* IEEE 802.11 standard does not require authentication in IBSS - * networks and most implementations do not seem to use it. - * However, try to reply to authentication attempts if someone - * has actually implemented this. - * TODO: Could implement shared key authentication. */ - if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) { - wpa_printf(MSG_DEBUG, "MLME: unexpected IBSS " - "authentication frame (alg=%d " - "transaction=%d)", - auth_alg, auth_transaction); - return; - } - ieee80211_send_auth(wpa_s, 2, NULL, 0, 0); - } - - if (auth_alg != wpa_s->mlme.auth_alg || - auth_transaction != wpa_s->mlme.auth_transaction) { - wpa_printf(MSG_DEBUG, "MLME: unexpected authentication frame " - "(alg=%d transaction=%d)", - auth_alg, auth_transaction); - return; - } - - if (status_code != WLAN_STATUS_SUCCESS) { - wpa_printf(MSG_DEBUG, "MLME: AP denied authentication " - "(auth_alg=%d code=%d)", wpa_s->mlme.auth_alg, - status_code); - if (status_code == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) { - const int num_algs = 3; - u8 algs[num_algs]; - int i, pos; - algs[0] = algs[1] = algs[2] = 0xff; - if (wpa_s->mlme.auth_algs & IEEE80211_AUTH_ALG_OPEN) - algs[0] = WLAN_AUTH_OPEN; - if (wpa_s->mlme.auth_algs & - IEEE80211_AUTH_ALG_SHARED_KEY) - algs[1] = WLAN_AUTH_SHARED_KEY; - if (wpa_s->mlme.auth_algs & IEEE80211_AUTH_ALG_LEAP) - algs[2] = WLAN_AUTH_LEAP; - if (wpa_s->mlme.auth_alg == WLAN_AUTH_OPEN) - pos = 0; - else if (wpa_s->mlme.auth_alg == WLAN_AUTH_SHARED_KEY) - pos = 1; - else - pos = 2; - for (i = 0; i < num_algs; i++) { - pos++; - if (pos >= num_algs) - pos = 0; - if (algs[pos] == wpa_s->mlme.auth_alg || - algs[pos] == 0xff) - continue; - if (algs[pos] == WLAN_AUTH_SHARED_KEY && - !ieee80211_sta_wep_configured(wpa_s)) - continue; - wpa_s->mlme.auth_alg = algs[pos]; - wpa_printf(MSG_DEBUG, "MLME: set auth_alg=%d " - "for next try", - wpa_s->mlme.auth_alg); - break; - } - } - return; - } - - switch (wpa_s->mlme.auth_alg) { - case WLAN_AUTH_OPEN: - case WLAN_AUTH_LEAP: - ieee80211_auth_completed(wpa_s); - break; - case WLAN_AUTH_SHARED_KEY: - if (wpa_s->mlme.auth_transaction == 4) - ieee80211_auth_completed(wpa_s); - else - ieee80211_auth_challenge(wpa_s, mgmt, len, - rx_status); - break; - } -} - - -static void ieee80211_rx_mgmt_deauth(struct wpa_supplicant *wpa_s, - struct ieee80211_mgmt *mgmt, - size_t len, - struct ieee80211_rx_status *rx_status) -{ - u16 reason_code; - - if (len < 24 + 2) { - wpa_printf(MSG_DEBUG, "MLME: too short (%lu) deauthentication " - "frame received from " MACSTR " - ignored", - (unsigned long) len, MAC2STR(mgmt->sa)); - return; - } - - if (os_memcmp(wpa_s->bssid, mgmt->sa, ETH_ALEN) != 0) { - wpa_printf(MSG_DEBUG, "MLME: deauthentication frame received " - "from unknown AP (SA=" MACSTR " BSSID=" MACSTR - ") - ignored", - MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid)); - return; - } - - reason_code = le_to_host16(mgmt->u.deauth.reason_code); - - wpa_printf(MSG_DEBUG, "MLME: RX deauthentication from " MACSTR - " (reason=%d)", MAC2STR(mgmt->sa), reason_code); - - if (wpa_s->mlme.authenticated) - wpa_printf(MSG_DEBUG, "MLME: deauthenticated"); - - if (wpa_s->mlme.state == IEEE80211_AUTHENTICATE || - wpa_s->mlme.state == IEEE80211_ASSOCIATE || - wpa_s->mlme.state == IEEE80211_ASSOCIATED) { - wpa_s->mlme.state = IEEE80211_AUTHENTICATE; - ieee80211_reschedule_timer(wpa_s, - IEEE80211_RETRY_AUTH_INTERVAL); - } - - ieee80211_set_associated(wpa_s, 0); - wpa_s->mlme.authenticated = 0; -} - - -static void ieee80211_rx_mgmt_disassoc(struct wpa_supplicant *wpa_s, - struct ieee80211_mgmt *mgmt, - size_t len, - struct ieee80211_rx_status *rx_status) -{ - u16 reason_code; - - if (len < 24 + 2) { - wpa_printf(MSG_DEBUG, "MLME: too short (%lu) disassociation " - "frame received from " MACSTR " - ignored", - (unsigned long) len, MAC2STR(mgmt->sa)); - return; - } - - if (os_memcmp(wpa_s->bssid, mgmt->sa, ETH_ALEN) != 0) { - wpa_printf(MSG_DEBUG, "MLME: disassociation frame received " - "from unknown AP (SA=" MACSTR " BSSID=" MACSTR - ") - ignored", - MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid)); - return; - } - - reason_code = le_to_host16(mgmt->u.disassoc.reason_code); - - wpa_printf(MSG_DEBUG, "MLME: RX disassociation from " MACSTR - " (reason=%d)", MAC2STR(mgmt->sa), reason_code); - - if (wpa_s->mlme.associated) - wpa_printf(MSG_DEBUG, "MLME: disassociated"); - - if (wpa_s->mlme.state == IEEE80211_ASSOCIATED) { - wpa_s->mlme.state = IEEE80211_ASSOCIATE; - ieee80211_reschedule_timer(wpa_s, - IEEE80211_RETRY_AUTH_INTERVAL); - } - - ieee80211_set_associated(wpa_s, 0); -} - - -static void ieee80211_rx_mgmt_assoc_resp(struct wpa_supplicant *wpa_s, - struct ieee80211_mgmt *mgmt, - size_t len, - struct ieee80211_rx_status *rx_status, - int reassoc) -{ - u8 rates[32]; - size_t rates_len; - u16 capab_info, status_code, aid; - struct ieee802_11_elems elems; - u8 *pos; - - /* AssocResp and ReassocResp have identical structure, so process both - * of them in this function. */ - - if (wpa_s->mlme.state != IEEE80211_ASSOCIATE) { - wpa_printf(MSG_DEBUG, "MLME: association frame received from " - MACSTR ", but not in associate state - ignored", - MAC2STR(mgmt->sa)); - return; - } - - if (len < 24 + 6) { - wpa_printf(MSG_DEBUG, "MLME: too short (%lu) association " - "frame received from " MACSTR " - ignored", - (unsigned long) len, MAC2STR(mgmt->sa)); - return; - } - - if (os_memcmp(wpa_s->bssid, mgmt->sa, ETH_ALEN) != 0) { - wpa_printf(MSG_DEBUG, "MLME: association frame received from " - "unknown AP (SA=" MACSTR " BSSID=" MACSTR ") - " - "ignored", MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid)); - return; - } - - capab_info = le_to_host16(mgmt->u.assoc_resp.capab_info); - status_code = le_to_host16(mgmt->u.assoc_resp.status_code); - aid = le_to_host16(mgmt->u.assoc_resp.aid); - if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) - wpa_printf(MSG_DEBUG, "MLME: invalid aid value %d; bits 15:14 " - "not set", aid); - aid &= ~(BIT(15) | BIT(14)); - - wpa_printf(MSG_DEBUG, "MLME: RX %sssocResp from " MACSTR - " (capab=0x%x status=%d aid=%d)", - reassoc ? "Rea" : "A", MAC2STR(mgmt->sa), - capab_info, status_code, aid); - - if (status_code != WLAN_STATUS_SUCCESS) { - wpa_printf(MSG_DEBUG, "MLME: AP denied association (code=%d)", - status_code); - return; - } - - pos = mgmt->u.assoc_resp.variable; - if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems) - == ParseFailed) { - wpa_printf(MSG_DEBUG, "MLME: failed to parse AssocResp"); - return; - } - - if (elems.supp_rates == NULL) { - wpa_printf(MSG_DEBUG, "MLME: no SuppRates element in " - "AssocResp"); - return; - } - - wpa_printf(MSG_DEBUG, "MLME: associated"); - wpa_s->mlme.aid = aid; - wpa_s->mlme.ap_capab = capab_info; - - os_free(wpa_s->mlme.assocresp_ies); - wpa_s->mlme.assocresp_ies_len = len - (pos - (u8 *) mgmt); - wpa_s->mlme.assocresp_ies = os_malloc(wpa_s->mlme.assocresp_ies_len); - if (wpa_s->mlme.assocresp_ies) { - os_memcpy(wpa_s->mlme.assocresp_ies, pos, - wpa_s->mlme.assocresp_ies_len); - } - - ieee80211_set_associated(wpa_s, 1); - - rates_len = elems.supp_rates_len; - if (rates_len > sizeof(rates)) - rates_len = sizeof(rates); - os_memcpy(rates, elems.supp_rates, rates_len); - if (elems.ext_supp_rates) { - size_t _len = elems.ext_supp_rates_len; - if (_len > sizeof(rates) - rates_len) - _len = sizeof(rates) - rates_len; - os_memcpy(rates + rates_len, elems.ext_supp_rates, _len); - rates_len += _len; - } - - if (wpa_drv_set_bssid(wpa_s, wpa_s->bssid) < 0) { - wpa_printf(MSG_DEBUG, "MLME: failed to set BSSID for the " - "netstack"); - } - if (wpa_drv_set_ssid(wpa_s, wpa_s->mlme.ssid, wpa_s->mlme.ssid_len) < - 0) { - wpa_printf(MSG_DEBUG, "MLME: failed to set SSID for the " - "netstack"); - } - - /* Remove STA entry before adding a new one just in case to avoid - * problems with existing configuration (e.g., keys). */ - wpa_drv_mlme_remove_sta(wpa_s, wpa_s->bssid); - if (wpa_drv_mlme_add_sta(wpa_s, wpa_s->bssid, rates, rates_len) < 0) { - wpa_printf(MSG_DEBUG, "MLME: failed to add STA entry to the " - "netstack"); - } - -#if 0 /* FIX? */ - sta->assoc_ap = 1; - - if (elems.wmm_param && wpa_s->mlme.wmm_enabled) { - sta->flags |= WLAN_STA_WME; - ieee80211_sta_wmm_params(wpa_s, elems.wmm_param, - elems.wmm_param_len); - } -#endif - - ieee80211_associated(wpa_s); -} - - -/* Caller must hold local->sta_bss_lock */ -static void __ieee80211_bss_hash_add(struct wpa_supplicant *wpa_s, - struct ieee80211_sta_bss *bss) -{ - bss->hnext = wpa_s->mlme.sta_bss_hash[STA_HASH(bss->bssid)]; - wpa_s->mlme.sta_bss_hash[STA_HASH(bss->bssid)] = bss; -} - - -/* Caller must hold local->sta_bss_lock */ -static void __ieee80211_bss_hash_del(struct wpa_supplicant *wpa_s, - struct ieee80211_sta_bss *bss) -{ - struct ieee80211_sta_bss *b, *prev = NULL; - b = wpa_s->mlme.sta_bss_hash[STA_HASH(bss->bssid)]; - while (b) { - if (b == bss) { - if (prev == NULL) { - wpa_s->mlme.sta_bss_hash[STA_HASH(bss->bssid)] - = bss->hnext; - } else { - prev->hnext = bss->hnext; - } - break; - } - prev = b; - b = b->hnext; - } -} - - -static struct ieee80211_sta_bss * -ieee80211_bss_add(struct wpa_supplicant *wpa_s, const u8 *bssid) -{ - struct ieee80211_sta_bss *bss; - - bss = os_zalloc(sizeof(*bss)); - if (bss == NULL) - return NULL; - os_memcpy(bss->bssid, bssid, ETH_ALEN); - - /* TODO: order by RSSI? */ - bss->next = wpa_s->mlme.sta_bss_list; - wpa_s->mlme.sta_bss_list = bss; - __ieee80211_bss_hash_add(wpa_s, bss); - return bss; -} - - -static struct ieee80211_sta_bss * -ieee80211_bss_get(struct wpa_supplicant *wpa_s, const u8 *bssid) -{ - struct ieee80211_sta_bss *bss; - - bss = wpa_s->mlme.sta_bss_hash[STA_HASH(bssid)]; - while (bss) { - if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0) - break; - bss = bss->hnext; - } - return bss; -} - - -static void ieee80211_bss_free(struct wpa_supplicant *wpa_s, - struct ieee80211_sta_bss *bss) -{ - __ieee80211_bss_hash_del(wpa_s, bss); - os_free(bss->wpa_ie); - os_free(bss->rsn_ie); - os_free(bss->wmm_ie); - os_free(bss); -} - - -static void ieee80211_bss_list_deinit(struct wpa_supplicant *wpa_s) -{ - struct ieee80211_sta_bss *bss, *prev; - - bss = wpa_s->mlme.sta_bss_list; - wpa_s->mlme.sta_bss_list = NULL; - while (bss) { - prev = bss; - bss = bss->next; - ieee80211_bss_free(wpa_s, prev); - } -} - - -static void ieee80211_bss_info(struct wpa_supplicant *wpa_s, - struct ieee80211_mgmt *mgmt, - size_t len, - struct ieee80211_rx_status *rx_status, - int beacon) -{ - struct ieee802_11_elems elems; - size_t baselen; - int channel, invalid = 0, clen; - struct ieee80211_sta_bss *bss; - u64 timestamp; - u8 *pos; - - if (!beacon && os_memcmp(mgmt->da, wpa_s->own_addr, ETH_ALEN)) - return; /* ignore ProbeResp to foreign address */ - -#if 0 - wpa_printf(MSG_MSGDUMP, "MLME: RX %s from " MACSTR " to " MACSTR, - beacon ? "Beacon" : "Probe Response", - MAC2STR(mgmt->sa), MAC2STR(mgmt->da)); -#endif - - baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt; - if (baselen > len) - return; - - pos = mgmt->u.beacon.timestamp; - timestamp = ((u64) pos[7] << 56) | ((u64) pos[6] << 48) | - ((u64) pos[5] << 40) | ((u64) pos[4] << 32) | - ((u64) pos[3] << 24) | ((u64) pos[2] << 16) | - ((u64) pos[1] << 8) | ((u64) pos[0]); - -#if 0 /* FIX */ - if (local->conf.mode == IW_MODE_ADHOC && beacon && - os_memcmp(mgmt->bssid, local->bssid, ETH_ALEN) == 0) { -#ifdef IEEE80211_IBSS_DEBUG - static unsigned long last_tsf_debug = 0; - u64 tsf; - if (local->hw->get_tsf) - tsf = local->hw->get_tsf(local->mdev); - else - tsf = -1LLU; - if (time_after(jiffies, last_tsf_debug + 5 * HZ)) { - wpa_printf(MSG_DEBUG, "RX beacon SA=" MACSTR " BSSID=" - MACSTR " TSF=0x%llx BCN=0x%llx diff=%lld " - "@%ld", - MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid), - tsf, timestamp, tsf - timestamp, jiffies); - last_tsf_debug = jiffies; - } -#endif /* IEEE80211_IBSS_DEBUG */ - } -#endif - - if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, - &elems) == ParseFailed) - invalid = 1; - -#if 0 /* FIX */ - if (local->conf.mode == IW_MODE_ADHOC && elems.supp_rates && - os_memcmp(mgmt->bssid, local->bssid, ETH_ALEN) == 0 && - (sta = sta_info_get(local, mgmt->sa))) { - struct ieee80211_rate *rates; - size_t num_rates; - u32 supp_rates, prev_rates; - int i, j, oper_mode; - - rates = local->curr_rates; - num_rates = local->num_curr_rates; - oper_mode = wpa_s->mlme.sta_scanning ? - local->scan_oper_phymode : local->conf.phymode; - for (i = 0; i < local->hw->num_modes; i++) { - struct ieee80211_hw_modes *mode = &local->hw->modes[i]; - if (oper_mode == mode->mode) { - rates = mode->rates; - num_rates = mode->num_rates; - break; - } - } - - supp_rates = 0; - for (i = 0; i < elems.supp_rates_len + - elems.ext_supp_rates_len; i++) { - u8 rate = 0; - int own_rate; - if (i < elems.supp_rates_len) - rate = elems.supp_rates[i]; - else if (elems.ext_supp_rates) - rate = elems.ext_supp_rates - [i - elems.supp_rates_len]; - own_rate = 5 * (rate & 0x7f); - if (oper_mode == MODE_ATHEROS_TURBO) - own_rate *= 2; - for (j = 0; j < num_rates; j++) - if (rates[j].rate == own_rate) - supp_rates |= BIT(j); - } - - prev_rates = sta->supp_rates; - sta->supp_rates &= supp_rates; - if (sta->supp_rates == 0) { - /* No matching rates - this should not really happen. - * Make sure that at least one rate is marked - * supported to avoid issues with TX rate ctrl. */ - sta->supp_rates = wpa_s->mlme.supp_rates_bits; - } - if (sta->supp_rates != prev_rates) { - wpa_printf(MSG_DEBUG, "MLME: updated supp_rates set " - "for " MACSTR " based on beacon info " - "(0x%x & 0x%x -> 0x%x)", - MAC2STR(sta->addr), prev_rates, - supp_rates, sta->supp_rates); - } - sta_info_release(local, sta); - } -#endif - - if (elems.ssid == NULL) - return; - - if (elems.ds_params && elems.ds_params_len == 1) - channel = elems.ds_params[0]; - else - channel = rx_status->channel; - - bss = ieee80211_bss_get(wpa_s, mgmt->bssid); - if (bss == NULL) { - bss = ieee80211_bss_add(wpa_s, mgmt->bssid); - if (bss == NULL) - return; - } else { -#if 0 - /* TODO: order by RSSI? */ - spin_lock_bh(&local->sta_bss_lock); - list_move_tail(&bss->list, &local->sta_bss_list); - spin_unlock_bh(&local->sta_bss_lock); -#endif - } - - if (bss->probe_resp && beacon) { - /* Do not allow beacon to override data from Probe Response. */ - return; - } - - bss->beacon_int = le_to_host16(mgmt->u.beacon.beacon_int); - bss->capability = le_to_host16(mgmt->u.beacon.capab_info); - if (elems.ssid && elems.ssid_len <= MAX_SSID_LEN) { - os_memcpy(bss->ssid, elems.ssid, elems.ssid_len); - bss->ssid_len = elems.ssid_len; - } - - bss->supp_rates_len = 0; - if (elems.supp_rates) { - clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; - if (clen > elems.supp_rates_len) - clen = elems.supp_rates_len; - os_memcpy(&bss->supp_rates[bss->supp_rates_len], - elems.supp_rates, clen); - bss->supp_rates_len += clen; - } - if (elems.ext_supp_rates) { - clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; - if (clen > elems.ext_supp_rates_len) - clen = elems.ext_supp_rates_len; - os_memcpy(&bss->supp_rates[bss->supp_rates_len], - elems.ext_supp_rates, clen); - bss->supp_rates_len += clen; - } - - if (elems.wpa && - (bss->wpa_ie == NULL || bss->wpa_ie_len != elems.wpa_len || - os_memcmp(bss->wpa_ie, elems.wpa, elems.wpa_len))) { - os_free(bss->wpa_ie); - bss->wpa_ie = os_malloc(elems.wpa_len + 2); - if (bss->wpa_ie) { - os_memcpy(bss->wpa_ie, elems.wpa - 2, - elems.wpa_len + 2); - bss->wpa_ie_len = elems.wpa_len + 2; - } else - bss->wpa_ie_len = 0; - } else if (!elems.wpa && bss->wpa_ie) { - os_free(bss->wpa_ie); - bss->wpa_ie = NULL; - bss->wpa_ie_len = 0; - } - - if (elems.rsn && - (bss->rsn_ie == NULL || bss->rsn_ie_len != elems.rsn_len || - os_memcmp(bss->rsn_ie, elems.rsn, elems.rsn_len))) { - os_free(bss->rsn_ie); - bss->rsn_ie = os_malloc(elems.rsn_len + 2); - if (bss->rsn_ie) { - os_memcpy(bss->rsn_ie, elems.rsn - 2, - elems.rsn_len + 2); - bss->rsn_ie_len = elems.rsn_len + 2; - } else - bss->rsn_ie_len = 0; - } else if (!elems.rsn && bss->rsn_ie) { - os_free(bss->rsn_ie); - bss->rsn_ie = NULL; - bss->rsn_ie_len = 0; - } - - if (elems.wmm_param && - (bss->wmm_ie == NULL || bss->wmm_ie_len != elems.wmm_param_len || - os_memcmp(bss->wmm_ie, elems.wmm_param, elems.wmm_param_len))) { - os_free(bss->wmm_ie); - bss->wmm_ie = os_malloc(elems.wmm_param_len + 2); - if (bss->wmm_ie) { - os_memcpy(bss->wmm_ie, elems.wmm_param - 2, - elems.wmm_param_len + 2); - bss->wmm_ie_len = elems.wmm_param_len + 2; - } else - bss->wmm_ie_len = 0; - } else if (!elems.wmm_param && bss->wmm_ie) { - os_free(bss->wmm_ie); - bss->wmm_ie = NULL; - bss->wmm_ie_len = 0; - } - - - bss->hw_mode = wpa_s->mlme.phymode; - bss->channel = channel; - bss->freq = wpa_s->mlme.freq; - if (channel != wpa_s->mlme.channel && - (wpa_s->mlme.phymode == WPA_MODE_IEEE80211G || - wpa_s->mlme.phymode == WPA_MODE_IEEE80211B) && - channel >= 1 && channel <= 14) { - static const int freq_list[] = { - 2412, 2417, 2422, 2427, 2432, 2437, 2442, - 2447, 2452, 2457, 2462, 2467, 2472, 2484 - }; - /* IEEE 802.11g/b mode can receive packets from neighboring - * channels, so map the channel into frequency. */ - bss->freq = freq_list[channel - 1]; - } - bss->timestamp = timestamp; - os_get_time(&bss->last_update); - bss->rssi = rx_status->ssi; - if (!beacon) - bss->probe_resp++; -} - - -static void ieee80211_rx_mgmt_probe_resp(struct wpa_supplicant *wpa_s, - struct ieee80211_mgmt *mgmt, - size_t len, - struct ieee80211_rx_status *rx_status) -{ - ieee80211_bss_info(wpa_s, mgmt, len, rx_status, 0); -} - - -static void ieee80211_rx_mgmt_beacon(struct wpa_supplicant *wpa_s, - struct ieee80211_mgmt *mgmt, - size_t len, - struct ieee80211_rx_status *rx_status) -{ - int use_protection; - size_t baselen; - struct ieee802_11_elems elems; - - ieee80211_bss_info(wpa_s, mgmt, len, rx_status, 1); - - if (!wpa_s->mlme.associated || - os_memcmp(wpa_s->bssid, mgmt->bssid, ETH_ALEN) != 0) - return; - - /* Process beacon from the current BSS */ - baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt; - if (baselen > len) - return; - - if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, - &elems) == ParseFailed) - return; - - use_protection = 0; - if (elems.erp_info && elems.erp_info_len >= 1) { - use_protection = - (elems.erp_info[0] & ERP_INFO_USE_PROTECTION) != 0; - } - - if (use_protection != !!wpa_s->mlme.use_protection) { - wpa_printf(MSG_DEBUG, "MLME: CTS protection %s (BSSID=" MACSTR - ")", - use_protection ? "enabled" : "disabled", - MAC2STR(wpa_s->bssid)); - wpa_s->mlme.use_protection = use_protection ? 1 : 0; - wpa_s->mlme.cts_protect_erp_frames = use_protection; - } - - if (elems.wmm_param && wpa_s->mlme.wmm_enabled) { - ieee80211_sta_wmm_params(wpa_s, elems.wmm_param, - elems.wmm_param_len); - } -} - - -static void ieee80211_rx_mgmt_probe_req(struct wpa_supplicant *wpa_s, - struct ieee80211_mgmt *mgmt, - size_t len, - struct ieee80211_rx_status *rx_status) -{ - int tx_last_beacon, adhoc; -#if 0 /* FIX */ - struct ieee80211_mgmt *resp; -#endif - u8 *pos, *end; - struct wpa_ssid *ssid = wpa_s->current_ssid; - - adhoc = ssid && ssid->mode == 1; - - if (!adhoc || wpa_s->mlme.state != IEEE80211_IBSS_JOINED || - len < 24 + 2 || wpa_s->mlme.probe_resp == NULL) - return; - -#if 0 /* FIX */ - if (local->hw->tx_last_beacon) - tx_last_beacon = local->hw->tx_last_beacon(local->mdev); - else -#endif - tx_last_beacon = 1; - -#ifdef IEEE80211_IBSS_DEBUG - wpa_printf(MSG_DEBUG, "MLME: RX ProbeReq SA=" MACSTR " DA=" MACSTR - " BSSID=" MACSTR " (tx_last_beacon=%d)", - MAC2STR(mgmt->sa), MAC2STR(mgmt->da), - MAC2STR(mgmt->bssid), tx_last_beacon); -#endif /* IEEE80211_IBSS_DEBUG */ - - if (!tx_last_beacon) - return; - - if (os_memcmp(mgmt->bssid, wpa_s->bssid, ETH_ALEN) != 0 && - os_memcmp(mgmt->bssid, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) != 0) - return; - - end = ((u8 *) mgmt) + len; - pos = mgmt->u.probe_req.variable; - if (pos[0] != WLAN_EID_SSID || - pos + 2 + pos[1] > end) { - wpa_printf(MSG_DEBUG, "MLME: Invalid SSID IE in ProbeReq from " - MACSTR, MAC2STR(mgmt->sa)); - return; - } - if (pos[1] != 0 && - (pos[1] != wpa_s->mlme.ssid_len || - os_memcmp(pos + 2, wpa_s->mlme.ssid, wpa_s->mlme.ssid_len) != 0)) - { - /* Ignore ProbeReq for foreign SSID */ - return; - } - -#if 0 /* FIX */ - /* Reply with ProbeResp */ - skb = skb_copy(wpa_s->mlme.probe_resp, GFP_ATOMIC); - if (skb == NULL) - return; - - resp = (struct ieee80211_mgmt *) skb->data; - os_memcpy(resp->da, mgmt->sa, ETH_ALEN); -#ifdef IEEE80211_IBSS_DEBUG - wpa_printf(MSG_DEBUG, "MLME: Sending ProbeResp to " MACSTR, - MAC2STR(resp->da)); -#endif /* IEEE80211_IBSS_DEBUG */ - ieee80211_sta_tx(wpa_s, skb, 0, 1); -#endif -} - - -static void ieee80211_sta_rx_mgmt(struct wpa_supplicant *wpa_s, - const u8 *buf, size_t len, - struct ieee80211_rx_status *rx_status) -{ - struct ieee80211_mgmt *mgmt; - u16 fc; - - if (len < 24) - return; - - mgmt = (struct ieee80211_mgmt *) buf; - fc = le_to_host16(mgmt->frame_control); - - switch (WLAN_FC_GET_STYPE(fc)) { - case WLAN_FC_STYPE_PROBE_REQ: - ieee80211_rx_mgmt_probe_req(wpa_s, mgmt, len, rx_status); - break; - case WLAN_FC_STYPE_PROBE_RESP: - ieee80211_rx_mgmt_probe_resp(wpa_s, mgmt, len, rx_status); - break; - case WLAN_FC_STYPE_BEACON: - ieee80211_rx_mgmt_beacon(wpa_s, mgmt, len, rx_status); - break; - case WLAN_FC_STYPE_AUTH: - ieee80211_rx_mgmt_auth(wpa_s, mgmt, len, rx_status); - break; - case WLAN_FC_STYPE_ASSOC_RESP: - ieee80211_rx_mgmt_assoc_resp(wpa_s, mgmt, len, rx_status, 0); - break; - case WLAN_FC_STYPE_REASSOC_RESP: - ieee80211_rx_mgmt_assoc_resp(wpa_s, mgmt, len, rx_status, 1); - break; - case WLAN_FC_STYPE_DEAUTH: - ieee80211_rx_mgmt_deauth(wpa_s, mgmt, len, rx_status); - break; - case WLAN_FC_STYPE_DISASSOC: - ieee80211_rx_mgmt_disassoc(wpa_s, mgmt, len, rx_status); - break; - default: - wpa_printf(MSG_DEBUG, "MLME: received unknown management " - "frame - stype=%d", WLAN_FC_GET_STYPE(fc)); - break; - } -} - - -static void ieee80211_sta_rx_scan(struct wpa_supplicant *wpa_s, - const u8 *buf, size_t len, - struct ieee80211_rx_status *rx_status) -{ - struct ieee80211_mgmt *mgmt; - u16 fc; - - if (len < 24) - return; - - mgmt = (struct ieee80211_mgmt *) buf; - fc = le_to_host16(mgmt->frame_control); - - if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT) { - if (WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_RESP) { - ieee80211_rx_mgmt_probe_resp(wpa_s, mgmt, - len, rx_status); - } else if (WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON) { - ieee80211_rx_mgmt_beacon(wpa_s, mgmt, len, rx_status); - } - } -} - - -static int ieee80211_sta_active_ibss(struct wpa_supplicant *wpa_s) -{ - int active = 0; - -#if 0 /* FIX */ - list_for_each(ptr, &local->sta_list) { - sta = list_entry(ptr, struct sta_info, list); - if (sta->dev == dev && - time_after(sta->last_rx + IEEE80211_IBSS_MERGE_INTERVAL, - jiffies)) { - active++; - break; - } - } -#endif - - return active; -} - - -static void ieee80211_sta_expire(struct wpa_supplicant *wpa_s) -{ -#if 0 /* FIX */ - list_for_each_safe(ptr, n, &local->sta_list) { - sta = list_entry(ptr, struct sta_info, list); - if (time_after(jiffies, sta->last_rx + - IEEE80211_IBSS_INACTIVITY_LIMIT)) { - wpa_printf(MSG_DEBUG, "MLME: expiring inactive STA " - MACSTR, MAC2STR(sta->addr)); - sta_info_free(local, sta, 1); - } - } -#endif -} - - -static void ieee80211_sta_merge_ibss(struct wpa_supplicant *wpa_s) -{ - ieee80211_reschedule_timer(wpa_s, IEEE80211_IBSS_MERGE_INTERVAL); - - ieee80211_sta_expire(wpa_s); - if (ieee80211_sta_active_ibss(wpa_s)) - return; - - wpa_printf(MSG_DEBUG, "MLME: No active IBSS STAs - trying to scan for " - "other IBSS networks with same SSID (merge)"); - ieee80211_sta_req_scan(wpa_s, wpa_s->mlme.ssid, wpa_s->mlme.ssid_len); -} - - -static void ieee80211_sta_timer(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_supplicant *wpa_s = eloop_ctx; - - switch (wpa_s->mlme.state) { - case IEEE80211_DISABLED: - break; - case IEEE80211_AUTHENTICATE: - ieee80211_authenticate(wpa_s); - break; - case IEEE80211_ASSOCIATE: - ieee80211_associate(wpa_s); - break; - case IEEE80211_ASSOCIATED: - ieee80211_associated(wpa_s); - break; - case IEEE80211_IBSS_SEARCH: - ieee80211_sta_find_ibss(wpa_s); - break; - case IEEE80211_IBSS_JOINED: - ieee80211_sta_merge_ibss(wpa_s); - break; - default: - wpa_printf(MSG_DEBUG, "ieee80211_sta_timer: Unknown state %d", - wpa_s->mlme.state); - break; - } - - if (ieee80211_privacy_mismatch(wpa_s)) { - wpa_printf(MSG_DEBUG, "MLME: privacy configuration mismatch " - "and mixed-cell disabled - disassociate"); - - ieee80211_send_disassoc(wpa_s, WLAN_REASON_UNSPECIFIED); - ieee80211_set_associated(wpa_s, 0); - } -} - - -static void ieee80211_sta_new_auth(struct wpa_supplicant *wpa_s) -{ - struct wpa_ssid *ssid = wpa_s->current_ssid; - if (ssid && ssid->mode != 0) - return; - -#if 0 /* FIX */ - if (local->hw->reset_tsf) { - /* Reset own TSF to allow time synchronization work. */ - local->hw->reset_tsf(local->mdev); - } -#endif - - wpa_s->mlme.wmm_last_param_set = -1; /* allow any WMM update */ - - - if (wpa_s->mlme.auth_algs & IEEE80211_AUTH_ALG_OPEN) - wpa_s->mlme.auth_alg = WLAN_AUTH_OPEN; - else if (wpa_s->mlme.auth_algs & IEEE80211_AUTH_ALG_SHARED_KEY) - wpa_s->mlme.auth_alg = WLAN_AUTH_SHARED_KEY; - else if (wpa_s->mlme.auth_algs & IEEE80211_AUTH_ALG_LEAP) - wpa_s->mlme.auth_alg = WLAN_AUTH_LEAP; - else - wpa_s->mlme.auth_alg = WLAN_AUTH_OPEN; - wpa_printf(MSG_DEBUG, "MLME: Initial auth_alg=%d", - wpa_s->mlme.auth_alg); - wpa_s->mlme.auth_transaction = -1; - wpa_s->mlme.auth_tries = wpa_s->mlme.assoc_tries = 0; - ieee80211_authenticate(wpa_s); -} - - -static int ieee80211_ibss_allowed(struct wpa_supplicant *wpa_s) -{ -#if 0 /* FIX */ - int m, c; - - for (m = 0; m < local->hw->num_modes; m++) { - struct ieee80211_hw_modes *mode = &local->hw->modes[m]; - if (mode->mode != local->conf.phymode) - continue; - for (c = 0; c < mode->num_channels; c++) { - struct ieee80211_channel *chan = &mode->channels[c]; - if (chan->flag & IEEE80211_CHAN_W_SCAN && - chan->chan == local->conf.channel) { - if (chan->flag & IEEE80211_CHAN_W_IBSS) - return 1; - break; - } - } - } -#endif - - return 0; -} - - -static int ieee80211_sta_join_ibss(struct wpa_supplicant *wpa_s, - struct ieee80211_sta_bss *bss) -{ - int res = 0, rates, done = 0; - struct ieee80211_mgmt *mgmt; -#if 0 /* FIX */ - struct ieee80211_tx_control control; - struct ieee80211_rate *rate; - struct rate_control_extra extra; -#endif - u8 *pos, *buf; - size_t len; - - /* Remove possible STA entries from other IBSS networks. */ -#if 0 /* FIX */ - sta_info_flush(local, NULL); - - if (local->hw->reset_tsf) { - /* Reset own TSF to allow time synchronization work. */ - local->hw->reset_tsf(local->mdev); - } -#endif - os_memcpy(wpa_s->bssid, bss->bssid, ETH_ALEN); - -#if 0 /* FIX */ - local->conf.beacon_int = bss->beacon_int >= 10 ? bss->beacon_int : 10; - - sdata->drop_unencrypted = bss->capability & - host_to_le16(WLAN_CAPABILITY_PRIVACY) ? 1 : 0; -#endif - -#if 0 /* FIX */ - os_memset(&rq, 0, sizeof(rq)); - rq.m = bss->freq * 100000; - rq.e = 1; - res = ieee80211_ioctl_siwfreq(wpa_s, NULL, &rq, NULL); -#endif - - if (!ieee80211_ibss_allowed(wpa_s)) { -#if 0 /* FIX */ - wpa_printf(MSG_DEBUG, "MLME: IBSS not allowed on channel %d " - "(%d MHz)", local->conf.channel, - local->conf.freq); -#endif - return -1; - } - - /* Set beacon template based on scan results */ - buf = os_malloc(400); - len = 0; - do { - if (buf == NULL) - break; - - mgmt = (struct ieee80211_mgmt *) buf; - len += 24 + sizeof(mgmt->u.beacon); - os_memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); - mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_BEACON); - os_memset(mgmt->da, 0xff, ETH_ALEN); - os_memcpy(mgmt->sa, wpa_s->own_addr, ETH_ALEN); - os_memcpy(mgmt->bssid, wpa_s->bssid, ETH_ALEN); -#if 0 /* FIX */ - mgmt->u.beacon.beacon_int = - host_to_le16(local->conf.beacon_int); -#endif - mgmt->u.beacon.capab_info = host_to_le16(bss->capability); - - pos = buf + len; - len += 2 + wpa_s->mlme.ssid_len; - *pos++ = WLAN_EID_SSID; - *pos++ = wpa_s->mlme.ssid_len; - os_memcpy(pos, wpa_s->mlme.ssid, wpa_s->mlme.ssid_len); - - rates = bss->supp_rates_len; - if (rates > 8) - rates = 8; - pos = buf + len; - len += 2 + rates; - *pos++ = WLAN_EID_SUPP_RATES; - *pos++ = rates; - os_memcpy(pos, bss->supp_rates, rates); - - pos = buf + len; - len += 2 + 1; - *pos++ = WLAN_EID_DS_PARAMS; - *pos++ = 1; - *pos++ = bss->channel; - - pos = buf + len; - len += 2 + 2; - *pos++ = WLAN_EID_IBSS_PARAMS; - *pos++ = 2; - /* FIX: set ATIM window based on scan results */ - *pos++ = 0; - *pos++ = 0; - - if (bss->supp_rates_len > 8) { - rates = bss->supp_rates_len - 8; - pos = buf + len; - len += 2 + rates; - *pos++ = WLAN_EID_EXT_SUPP_RATES; - *pos++ = rates; - os_memcpy(pos, &bss->supp_rates[8], rates); - } - -#if 0 /* FIX */ - os_memset(&control, 0, sizeof(control)); - control.pkt_type = PKT_PROBE_RESP; - os_memset(&extra, 0, sizeof(extra)); - extra.endidx = local->num_curr_rates; - rate = rate_control_get_rate(wpa_s, skb, &extra); - if (rate == NULL) { - wpa_printf(MSG_DEBUG, "MLME: Failed to determine TX " - "rate for IBSS beacon"); - break; - } - control.tx_rate = (wpa_s->mlme.short_preamble && - (rate->flags & IEEE80211_RATE_PREAMBLE2)) ? - rate->val2 : rate->val; - control.antenna_sel = local->conf.antenna_sel; - control.power_level = local->conf.power_level; - control.no_ack = 1; - control.retry_limit = 1; - control.rts_cts_duration = 0; -#endif - -#if 0 /* FIX */ - wpa_s->mlme.probe_resp = skb_copy(skb, GFP_ATOMIC); - if (wpa_s->mlme.probe_resp) { - mgmt = (struct ieee80211_mgmt *) - wpa_s->mlme.probe_resp->data; - mgmt->frame_control = - IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_PROBE_RESP); - } else { - wpa_printf(MSG_DEBUG, "MLME: Could not allocate " - "ProbeResp template for IBSS"); - } - - if (local->hw->beacon_update && - local->hw->beacon_update(wpa_s, skb, &control) == 0) { - wpa_printf(MSG_DEBUG, "MLME: Configured IBSS beacon " - "template based on scan results"); - skb = NULL; - } - - rates = 0; - for (i = 0; i < bss->supp_rates_len; i++) { - int rate = (bss->supp_rates[i] & 0x7f) * 5; - if (local->conf.phymode == MODE_ATHEROS_TURBO) - rate *= 2; - for (j = 0; j < local->num_curr_rates; j++) - if (local->curr_rates[j].rate == rate) - rates |= BIT(j); - } - wpa_s->mlme.supp_rates_bits = rates; -#endif - done = 1; - } while (0); - - os_free(buf); - if (!done) { - wpa_printf(MSG_DEBUG, "MLME: Failed to configure IBSS beacon " - "template"); - } - - wpa_s->mlme.state = IEEE80211_IBSS_JOINED; - ieee80211_reschedule_timer(wpa_s, IEEE80211_IBSS_MERGE_INTERVAL); - - return res; -} - - -#if 0 /* FIX */ -static int ieee80211_sta_create_ibss(struct wpa_supplicant *wpa_s) -{ - struct ieee80211_sta_bss *bss; - u8 bssid[ETH_ALEN], *pos; - int i; - -#if 0 - /* Easier testing, use fixed BSSID. */ - os_memset(bssid, 0xfe, ETH_ALEN); -#else - /* Generate random, not broadcast, locally administered BSSID. Mix in - * own MAC address to make sure that devices that do not have proper - * random number generator get different BSSID. */ - os_get_random(bssid, ETH_ALEN); - for (i = 0; i < ETH_ALEN; i++) - bssid[i] ^= wpa_s->own_addr[i]; - bssid[0] &= ~0x01; - bssid[0] |= 0x02; -#endif - - wpa_printf(MSG_DEBUG, "MLME: Creating new IBSS network, BSSID " - MACSTR "", MAC2STR(bssid)); - - bss = ieee80211_bss_add(wpa_s, bssid); - if (bss == NULL) - return -ENOMEM; - -#if 0 /* FIX */ - if (local->conf.beacon_int == 0) - local->conf.beacon_int = 100; - bss->beacon_int = local->conf.beacon_int; - bss->hw_mode = local->conf.phymode; - bss->channel = local->conf.channel; - bss->freq = local->conf.freq; -#endif - os_get_time(&bss->last_update); - bss->capability = host_to_le16(WLAN_CAPABILITY_IBSS); -#if 0 /* FIX */ - if (sdata->default_key) { - bss->capability |= host_to_le16(WLAN_CAPABILITY_PRIVACY); - } else - sdata->drop_unencrypted = 0; - bss->supp_rates_len = local->num_curr_rates; -#endif - pos = bss->supp_rates; -#if 0 /* FIX */ - for (i = 0; i < local->num_curr_rates; i++) { - int rate = local->curr_rates[i].rate; - if (local->conf.phymode == MODE_ATHEROS_TURBO) - rate /= 2; - *pos++ = (u8) (rate / 5); - } -#endif - - return ieee80211_sta_join_ibss(wpa_s, bss); -} -#endif - - -static int ieee80211_sta_find_ibss(struct wpa_supplicant *wpa_s) -{ - struct ieee80211_sta_bss *bss; - int found = 0; - u8 bssid[ETH_ALEN]; - int active_ibss; - struct os_time now; - - if (wpa_s->mlme.ssid_len == 0) - return -EINVAL; - - active_ibss = ieee80211_sta_active_ibss(wpa_s); -#ifdef IEEE80211_IBSS_DEBUG - wpa_printf(MSG_DEBUG, "MLME: sta_find_ibss (active_ibss=%d)", - active_ibss); -#endif /* IEEE80211_IBSS_DEBUG */ - for (bss = wpa_s->mlme.sta_bss_list; bss; bss = bss->next) { - if (wpa_s->mlme.ssid_len != bss->ssid_len || - os_memcmp(wpa_s->mlme.ssid, bss->ssid, bss->ssid_len) != 0 - || !(bss->capability & WLAN_CAPABILITY_IBSS)) - continue; -#ifdef IEEE80211_IBSS_DEBUG - wpa_printf(MSG_DEBUG, " bssid=" MACSTR " found", - MAC2STR(bss->bssid)); -#endif /* IEEE80211_IBSS_DEBUG */ - os_memcpy(bssid, bss->bssid, ETH_ALEN); - found = 1; - if (active_ibss || - os_memcmp(bssid, wpa_s->bssid, ETH_ALEN) != 0) - break; - } - -#ifdef IEEE80211_IBSS_DEBUG - wpa_printf(MSG_DEBUG, " sta_find_ibss: selected " MACSTR " current " - MACSTR, MAC2STR(bssid), MAC2STR(wpa_s->bssid)); -#endif /* IEEE80211_IBSS_DEBUG */ - if (found && os_memcmp(wpa_s->bssid, bssid, ETH_ALEN) != 0 && - (bss = ieee80211_bss_get(wpa_s, bssid))) { - wpa_printf(MSG_DEBUG, "MLME: Selected IBSS BSSID " MACSTR - " based on configured SSID", - MAC2STR(bssid)); - return ieee80211_sta_join_ibss(wpa_s, bss); - } -#ifdef IEEE80211_IBSS_DEBUG - wpa_printf(MSG_DEBUG, " did not try to join ibss"); -#endif /* IEEE80211_IBSS_DEBUG */ - - /* Selected IBSS not found in current scan results - try to scan */ - os_get_time(&now); -#if 0 /* FIX */ - if (wpa_s->mlme.state == IEEE80211_IBSS_JOINED && - !ieee80211_sta_active_ibss(wpa_s)) { - ieee80211_reschedule_timer(wpa_s, - IEEE80211_IBSS_MERGE_INTERVAL); - } else if (time_after(jiffies, wpa_s->mlme.last_scan_completed + - IEEE80211_SCAN_INTERVAL)) { - wpa_printf(MSG_DEBUG, "MLME: Trigger new scan to find an IBSS " - "to join"); - return ieee80211_sta_req_scan(wpa_s->mlme.ssid, - wpa_s->mlme.ssid_len); - } else if (wpa_s->mlme.state != IEEE80211_IBSS_JOINED) { - int interval = IEEE80211_SCAN_INTERVAL; - - if (time_after(jiffies, wpa_s->mlme.ibss_join_req + - IEEE80211_IBSS_JOIN_TIMEOUT)) { - if (wpa_s->mlme.create_ibss && - ieee80211_ibss_allowed(wpa_s)) - return ieee80211_sta_create_ibss(wpa_s); - if (wpa_s->mlme.create_ibss) { - wpa_printf(MSG_DEBUG, "MLME: IBSS not allowed " - "on the configured channel %d " - "(%d MHz)", - local->conf.channel, - local->conf.freq); - } - - /* No IBSS found - decrease scan interval and continue - * scanning. */ - interval = IEEE80211_SCAN_INTERVAL_SLOW; - } - - wpa_s->mlme.state = IEEE80211_IBSS_SEARCH; - ieee80211_reschedule_timer(wpa_s, interval); - return 0; - } -#endif - - return 0; -} - - -int ieee80211_sta_get_ssid(struct wpa_supplicant *wpa_s, u8 *ssid, - size_t *len) -{ - os_memcpy(ssid, wpa_s->mlme.ssid, wpa_s->mlme.ssid_len); - *len = wpa_s->mlme.ssid_len; - return 0; -} - - -int ieee80211_sta_associate(struct wpa_supplicant *wpa_s, - struct wpa_driver_associate_params *params) -{ - struct ieee80211_sta_bss *bss; - - wpa_s->mlme.bssid_set = 0; - wpa_s->mlme.freq = params->freq; - if (params->bssid) { - os_memcpy(wpa_s->bssid, params->bssid, ETH_ALEN); - if (os_memcmp(params->bssid, "\x00\x00\x00\x00\x00\x00", - ETH_ALEN)) - wpa_s->mlme.bssid_set = 1; - bss = ieee80211_bss_get(wpa_s, wpa_s->bssid); - if (bss) { - wpa_s->mlme.phymode = bss->hw_mode; - wpa_s->mlme.channel = bss->channel; - wpa_s->mlme.freq = bss->freq; - } - } - -#if 0 /* FIX */ - /* TODO: This should always be done for IBSS, even if IEEE80211_QOS is - * not defined. */ - if (local->hw->conf_tx) { - struct ieee80211_tx_queue_params qparam; - int i; - - os_memset(&qparam, 0, sizeof(qparam)); - /* TODO: are these ok defaults for all hw_modes? */ - qparam.aifs = 2; - qparam.cw_min = - local->conf.phymode == MODE_IEEE80211B ? 31 : 15; - qparam.cw_max = 1023; - qparam.burst_time = 0; - for (i = IEEE80211_TX_QUEUE_DATA0; i < NUM_TX_DATA_QUEUES; i++) - { - local->hw->conf_tx(wpa_s, i + IEEE80211_TX_QUEUE_DATA0, - &qparam); - } - /* IBSS uses different parameters for Beacon sending */ - qparam.cw_min++; - qparam.cw_min *= 2; - qparam.cw_min--; - local->hw->conf_tx(wpa_s, IEEE80211_TX_QUEUE_BEACON, &qparam); - } -#endif - - if (wpa_s->mlme.ssid_len != params->ssid_len || - os_memcmp(wpa_s->mlme.ssid, params->ssid, params->ssid_len) != 0) - wpa_s->mlme.prev_bssid_set = 0; - os_memcpy(wpa_s->mlme.ssid, params->ssid, params->ssid_len); - os_memset(wpa_s->mlme.ssid + params->ssid_len, 0, - MAX_SSID_LEN - params->ssid_len); - wpa_s->mlme.ssid_len = params->ssid_len; - wpa_s->mlme.ssid_set = 1; - - os_free(wpa_s->mlme.extra_ie); - if (params->wpa_ie == NULL || params->wpa_ie_len == 0) { - wpa_s->mlme.extra_ie = NULL; - wpa_s->mlme.extra_ie_len = 0; - return 0; - } - wpa_s->mlme.extra_ie = os_malloc(params->wpa_ie_len); - if (wpa_s->mlme.extra_ie == NULL) { - wpa_s->mlme.extra_ie_len = 0; - return -1; - } - os_memcpy(wpa_s->mlme.extra_ie, params->wpa_ie, params->wpa_ie_len); - wpa_s->mlme.extra_ie_len = params->wpa_ie_len; - - wpa_s->mlme.key_mgmt = params->key_mgmt_suite; - - ieee80211_sta_set_channel(wpa_s, wpa_s->mlme.phymode, - wpa_s->mlme.channel, wpa_s->mlme.freq); - - if (params->mode == 1 && !wpa_s->mlme.bssid_set) { - os_get_time(&wpa_s->mlme.ibss_join_req); - wpa_s->mlme.state = IEEE80211_IBSS_SEARCH; - return ieee80211_sta_find_ibss(wpa_s); - } - - if (wpa_s->mlme.bssid_set) - ieee80211_sta_new_auth(wpa_s); - - return 0; -} - - -static void ieee80211_sta_save_oper_chan(struct wpa_supplicant *wpa_s) -{ - wpa_s->mlme.scan_oper_channel = wpa_s->mlme.channel; - wpa_s->mlme.scan_oper_freq = wpa_s->mlme.freq; - wpa_s->mlme.scan_oper_phymode = wpa_s->mlme.phymode; -} - - -static int ieee80211_sta_restore_oper_chan(struct wpa_supplicant *wpa_s) -{ - wpa_s->mlme.channel = wpa_s->mlme.scan_oper_channel; - wpa_s->mlme.freq = wpa_s->mlme.scan_oper_freq; - wpa_s->mlme.phymode = wpa_s->mlme.scan_oper_phymode; - if (wpa_s->mlme.freq == 0) - return 0; - return ieee80211_sta_set_channel(wpa_s, wpa_s->mlme.phymode, - wpa_s->mlme.channel, - wpa_s->mlme.freq); -} - - -static int ieee80211_active_scan(struct wpa_supplicant *wpa_s) -{ - size_t m; - int c; - - for (m = 0; m < wpa_s->mlme.num_modes; m++) { - struct wpa_hw_modes *mode = &wpa_s->mlme.modes[m]; - if ((int) mode->mode != (int) wpa_s->mlme.phymode) - continue; - for (c = 0; c < mode->num_channels; c++) { - struct wpa_channel_data *chan = &mode->channels[c]; - if (chan->flag & WPA_CHAN_W_SCAN && - chan->chan == wpa_s->mlme.channel) { - if (chan->flag & WPA_CHAN_W_ACTIVE_SCAN) - return 1; - break; - } - } - } - - return 0; -} - - -static void ieee80211_sta_scan_timer(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_supplicant *wpa_s = eloop_ctx; - struct wpa_hw_modes *mode; - struct wpa_channel_data *chan; - int skip = 0; - int timeout = 0; - struct wpa_ssid *ssid = wpa_s->current_ssid; - int adhoc; - - if (!wpa_s->mlme.sta_scanning || wpa_s->mlme.modes == NULL) - return; - - adhoc = ssid && ssid->mode == 1; - - switch (wpa_s->mlme.scan_state) { - case SCAN_SET_CHANNEL: - mode = &wpa_s->mlme.modes[wpa_s->mlme.scan_hw_mode_idx]; - if (wpa_s->mlme.scan_hw_mode_idx >= - (int) wpa_s->mlme.num_modes || - (wpa_s->mlme.scan_hw_mode_idx + 1 == - (int) wpa_s->mlme.num_modes - && wpa_s->mlme.scan_channel_idx >= mode->num_channels)) { - if (ieee80211_sta_restore_oper_chan(wpa_s)) { - wpa_printf(MSG_DEBUG, "MLME: failed to " - "restore operational channel after " - "scan"); - } - wpa_printf(MSG_DEBUG, "MLME: scan completed"); - wpa_s->mlme.sta_scanning = 0; - os_get_time(&wpa_s->mlme.last_scan_completed); - wpa_supplicant_event(wpa_s, EVENT_SCAN_RESULTS, NULL); - if (adhoc) { - if (!wpa_s->mlme.bssid_set || - (wpa_s->mlme.state == - IEEE80211_IBSS_JOINED && - !ieee80211_sta_active_ibss(wpa_s))) - ieee80211_sta_find_ibss(wpa_s); - } - return; - } - skip = !(wpa_s->mlme.hw_modes & (1 << mode->mode)); - chan = &mode->channels[wpa_s->mlme.scan_channel_idx]; - if (!(chan->flag & WPA_CHAN_W_SCAN) || - (adhoc && !(chan->flag & WPA_CHAN_W_IBSS)) || - (wpa_s->mlme.hw_modes & (1 << WPA_MODE_IEEE80211G) && - mode->mode == WPA_MODE_IEEE80211B && - wpa_s->mlme.scan_skip_11b)) - skip = 1; - - if (!skip) { - wpa_printf(MSG_MSGDUMP, - "MLME: scan channel %d (%d MHz)", - chan->chan, chan->freq); - - wpa_s->mlme.channel = chan->chan; - wpa_s->mlme.freq = chan->freq; - wpa_s->mlme.phymode = mode->mode; - if (ieee80211_sta_set_channel(wpa_s, mode->mode, - chan->chan, chan->freq)) - { - wpa_printf(MSG_DEBUG, "MLME: failed to set " - "channel %d (%d MHz) for scan", - chan->chan, chan->freq); - skip = 1; - } - } - - wpa_s->mlme.scan_channel_idx++; - if (wpa_s->mlme.scan_channel_idx >= - wpa_s->mlme.modes[wpa_s->mlme.scan_hw_mode_idx]. - num_channels) { - wpa_s->mlme.scan_hw_mode_idx++; - wpa_s->mlme.scan_channel_idx = 0; - } - - if (skip) { - timeout = 0; - break; - } - - timeout = IEEE80211_PROBE_DELAY; - wpa_s->mlme.scan_state = SCAN_SEND_PROBE; - break; - case SCAN_SEND_PROBE: - if (ieee80211_active_scan(wpa_s)) { - ieee80211_send_probe_req(wpa_s, NULL, - wpa_s->mlme.scan_ssid, - wpa_s->mlme.scan_ssid_len); - timeout = IEEE80211_CHANNEL_TIME; - } else { - timeout = IEEE80211_PASSIVE_CHANNEL_TIME; - } - wpa_s->mlme.scan_state = SCAN_SET_CHANNEL; - break; - } - - eloop_register_timeout(timeout / 1000, 1000 * (timeout % 1000), - ieee80211_sta_scan_timer, wpa_s, NULL); -} - - -int ieee80211_sta_req_scan(struct wpa_supplicant *wpa_s, const u8 *ssid, - size_t ssid_len) -{ - if (ssid_len > MAX_SSID_LEN) - return -1; - - /* MLME-SCAN.request (page 118) page 144 (11.1.3.1) - * BSSType: INFRASTRUCTURE, INDEPENDENT, ANY_BSS - * BSSID: MACAddress - * SSID - * ScanType: ACTIVE, PASSIVE - * ProbeDelay: delay (in microseconds) to be used prior to transmitting - * a Probe frame during active scanning - * ChannelList - * MinChannelTime (>= ProbeDelay), in TU - * MaxChannelTime: (>= MinChannelTime), in TU - */ - - /* MLME-SCAN.confirm - * BSSDescriptionSet - * ResultCode: SUCCESS, INVALID_PARAMETERS - */ - - /* TODO: if assoc, move to power save mode for the duration of the - * scan */ - - if (wpa_s->mlme.sta_scanning) - return -1; - - wpa_printf(MSG_DEBUG, "MLME: starting scan"); - - ieee80211_sta_save_oper_chan(wpa_s); - - wpa_s->mlme.sta_scanning = 1; - /* TODO: stop TX queue? */ - - if (ssid) { - wpa_s->mlme.scan_ssid_len = ssid_len; - os_memcpy(wpa_s->mlme.scan_ssid, ssid, ssid_len); - } else - wpa_s->mlme.scan_ssid_len = 0; - wpa_s->mlme.scan_skip_11b = 1; /* FIX: clear this is 11g is not - * supported */ - wpa_s->mlme.scan_state = SCAN_SET_CHANNEL; - wpa_s->mlme.scan_hw_mode_idx = 0; - wpa_s->mlme.scan_channel_idx = 0; - eloop_register_timeout(0, 1, ieee80211_sta_scan_timer, wpa_s, NULL); - - return 0; -} - - -int ieee80211_sta_get_scan_results(struct wpa_supplicant *wpa_s, - struct wpa_scan_result *results, - size_t max_size) -{ - size_t ap_num = 0; - struct wpa_scan_result *r; - struct ieee80211_sta_bss *bss; - - os_memset(results, 0, max_size * sizeof(struct wpa_scan_result)); - for (bss = wpa_s->mlme.sta_bss_list; bss; bss = bss->next) { - r = &results[ap_num]; - os_memcpy(r->bssid, bss->bssid, ETH_ALEN); - os_memcpy(r->ssid, bss->ssid, bss->ssid_len); - r->ssid_len = bss->ssid_len; - if (bss->wpa_ie && bss->wpa_ie_len < SSID_MAX_WPA_IE_LEN) { - os_memcpy(r->wpa_ie, bss->wpa_ie, bss->wpa_ie_len); - r->wpa_ie_len = bss->wpa_ie_len; - } - if (bss->rsn_ie && bss->rsn_ie_len < SSID_MAX_WPA_IE_LEN) { - os_memcpy(r->rsn_ie, bss->rsn_ie, bss->rsn_ie_len); - r->rsn_ie_len = bss->rsn_ie_len; - } - r->freq = bss->freq; - r->caps = bss->capability; - r->level = bss->rssi; - - ap_num++; - if (ap_num >= max_size) - break; - } - - return ap_num; -} - - -#if 0 /* FIX */ -struct sta_info * ieee80211_ibss_add_sta(struct wpa_supplicant *wpa_s, - struct sk_buff *skb, u8 *bssid, - u8 *addr) -{ - struct ieee80211_local *local = dev->priv; - struct list_head *ptr; - struct sta_info *sta; - struct wpa_supplicant *sta_dev = NULL; - - /* TODO: Could consider removing the least recently used entry and - * allow new one to be added. */ - if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) { - if (net_ratelimit()) { - wpa_printf(MSG_DEBUG, "MLME: No room for a new IBSS " - "STA entry " MACSTR, MAC2STR(addr)); - } - return NULL; - } - - spin_lock_bh(&local->sub_if_lock); - list_for_each(ptr, &local->sub_if_list) { - sdata = list_entry(ptr, struct ieee80211_sub_if_data, list); - if (sdata->type == IEEE80211_SUB_IF_TYPE_STA && - os_memcmp(bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) { - sta_dev = sdata->dev; - break; - } - } - spin_unlock_bh(&local->sub_if_lock); - - if (sta_dev == NULL) - return NULL; - - wpa_printf(MSG_DEBUG, "MLME: Adding new IBSS station " MACSTR - " (dev=%s)", MAC2STR(addr), sta_dev->name); - - sta = sta_info_add(wpa_s, addr); - if (sta == NULL) { - return NULL; - } - - sta->dev = sta_dev; - sta->supp_rates = wpa_s->mlme.supp_rates_bits; - - rate_control_rate_init(local, sta); - - return sta; /* caller will call sta_info_release() */ -} -#endif - - -int ieee80211_sta_deauthenticate(struct wpa_supplicant *wpa_s, u16 reason) -{ - wpa_printf(MSG_DEBUG, "MLME: deauthenticate(reason=%d)", reason); - - ieee80211_send_deauth(wpa_s, reason); - ieee80211_set_associated(wpa_s, 0); - return 0; -} - - -int ieee80211_sta_disassociate(struct wpa_supplicant *wpa_s, u16 reason) -{ - wpa_printf(MSG_DEBUG, "MLME: disassociate(reason=%d)", reason); - - if (!wpa_s->mlme.associated) - return -1; - - ieee80211_send_disassoc(wpa_s, reason); - ieee80211_set_associated(wpa_s, 0); - return 0; -} - - -void ieee80211_sta_rx(struct wpa_supplicant *wpa_s, const u8 *buf, size_t len, - struct ieee80211_rx_status *rx_status) -{ - struct ieee80211_mgmt *mgmt; - u16 fc; - const u8 *pos; - - /* wpa_hexdump(MSG_MSGDUMP, "MLME: Received frame", buf, len); */ - - if (wpa_s->mlme.sta_scanning) { - ieee80211_sta_rx_scan(wpa_s, buf, len, rx_status); - return; - } - - if (len < 24) - return; - - mgmt = (struct ieee80211_mgmt *) buf; - fc = le_to_host16(mgmt->frame_control); - - if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT) - ieee80211_sta_rx_mgmt(wpa_s, buf, len, rx_status); - else if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_DATA) { - if ((fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) != - WLAN_FC_FROMDS) - return; - /* mgmt->sa is actually BSSID for FromDS data frames */ - if (os_memcmp(mgmt->sa, wpa_s->bssid, ETH_ALEN) != 0) - return; - /* Skip IEEE 802.11 and LLC headers */ - pos = buf + 24 + 6; - if (WPA_GET_BE16(pos) != ETH_P_EAPOL) - return; - pos += 2; - /* mgmt->bssid is actually BSSID for SA data frames */ - wpa_supplicant_rx_eapol(wpa_s, mgmt->bssid, - pos, buf + len - pos); - } -} - - -void ieee80211_sta_free_hw_features(struct wpa_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 ieee80211_sta_init(struct wpa_supplicant *wpa_s) -{ - u16 num_modes, flags; - - wpa_s->mlme.modes = wpa_drv_get_hw_feature_data(wpa_s, &num_modes, - &flags); - if (wpa_s->mlme.modes == NULL) { - wpa_printf(MSG_ERROR, "MLME: Failed to read supported " - "channels and rates from the driver"); - return -1; - } - - wpa_s->mlme.num_modes = num_modes; - - wpa_s->mlme.hw_modes = 1 << WPA_MODE_IEEE80211A; - wpa_s->mlme.hw_modes |= 1 << WPA_MODE_IEEE80211B; - wpa_s->mlme.hw_modes |= 1 << WPA_MODE_IEEE80211G; - - return 0; -} - - -void ieee80211_sta_deinit(struct wpa_supplicant *wpa_s) -{ - eloop_cancel_timeout(ieee80211_sta_timer, wpa_s, NULL); - eloop_cancel_timeout(ieee80211_sta_scan_timer, wpa_s, NULL); - os_free(wpa_s->mlme.extra_ie); - wpa_s->mlme.extra_ie = NULL; - os_free(wpa_s->mlme.assocreq_ies); - wpa_s->mlme.assocreq_ies = NULL; - os_free(wpa_s->mlme.assocresp_ies); - wpa_s->mlme.assocresp_ies = NULL; - ieee80211_bss_list_deinit(wpa_s); - ieee80211_sta_free_hw_features(wpa_s->mlme.modes, - wpa_s->mlme.num_modes); -} diff --git a/contrib/wpa_supplicant/mlme.h b/contrib/wpa_supplicant/mlme.h deleted file mode 100644 index 9f6f5eb2acd5..000000000000 --- a/contrib/wpa_supplicant/mlme.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * WPA Supplicant - Client mode MLME - * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi> - * Copyright (c) 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 MLME_H -#define MLME_H - -#ifdef CONFIG_CLIENT_MLME - -int ieee80211_sta_init(struct wpa_supplicant *wpa_s); -void ieee80211_sta_deinit(struct wpa_supplicant *wpa_s); -int ieee80211_sta_req_scan(struct wpa_supplicant *wpa_s, const u8 *ssid, - size_t ssid_len); -int ieee80211_sta_deauthenticate(struct wpa_supplicant *wpa_s, u16 reason); -int ieee80211_sta_disassociate(struct wpa_supplicant *wpa_s, u16 reason); -int ieee80211_sta_associate(struct wpa_supplicant *wpa_s, - struct wpa_driver_associate_params *params); -int ieee80211_sta_get_ssid(struct wpa_supplicant *wpa_s, u8 *ssid, - size_t *len); -void ieee80211_sta_free_hw_features(struct wpa_hw_modes *hw_features, - size_t num_hw_features); -void ieee80211_sta_rx(struct wpa_supplicant *wpa_s, const u8 *buf, size_t len, - struct ieee80211_rx_status *rx_status); -int ieee80211_sta_get_scan_results(struct wpa_supplicant *wpa_s, - struct wpa_scan_result *results, - size_t max_size); - -#else /* CONFIG_CLIENT_MLME */ - -static inline int ieee80211_sta_init(struct wpa_supplicant *wpa_s) -{ - return 0; -} - -static inline void ieee80211_sta_deinit(struct wpa_supplicant *wpa_s) -{ -} - -static inline int ieee80211_sta_req_scan(struct wpa_supplicant *wpa_s, - const u8 *ssid, size_t ssid_len) -{ - return -1; -} - -static inline int ieee80211_sta_deauthenticate(struct wpa_supplicant *wpa_s, - u16 reason) -{ - return -1; -} - -static inline int ieee80211_sta_disassociate(struct wpa_supplicant *wpa_s, - u16 reason) -{ - return -1; -} - -static inline int -ieee80211_sta_associate(struct wpa_supplicant *wpa_s, - struct wpa_driver_associate_params *params) -{ - return -1; -} - -static inline int ieee80211_sta_get_ssid(struct wpa_supplicant *wpa_s, - u8 *ssid, size_t *len) -{ - return -1; -} - -static inline void -ieee80211_sta_free_hw_features(struct wpa_hw_modes *hw_features, - size_t num_hw_features) -{ -} - -static inline void -ieee80211_sta_rx(struct wpa_supplicant *wpa_s, const u8 *buf, size_t len, - struct ieee80211_rx_status *rx_status) -{ -} - -static inline int -ieee80211_sta_get_scan_results(struct wpa_supplicant *wpa_s, - struct wpa_scan_result *results, - size_t max_size) -{ - return -1; -} - -#endif /* CONFIG_CLIENT_MLME */ - -#endif /* MLME_H */ diff --git a/contrib/wpa_supplicant/ms_funcs.c b/contrib/wpa_supplicant/ms_funcs.c deleted file mode 100644 index d7231799d1c7..000000000000 --- a/contrib/wpa_supplicant/ms_funcs.c +++ /dev/null @@ -1,440 +0,0 @@ -/* - * WPA Supplicant / shared MSCHAPV2 helper functions / RFC 2433 / RFC 2759 - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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" -#include "rc4.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) - */ -static void 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; - - sha1_vector(3, addr, len, hash); - os_memcpy(challenge, hash, 8); -} - - -/** - * 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) - */ -void 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) - return; - - /* 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; - 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) - */ -void hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash) -{ - size_t len = 16; - 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_hallenge: 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) - */ -void 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); - nt_password_hash(password, password_len, password_hash); - challenge_response(challenge, password_hash, response); -} - - -/** - * generate_nt_response_pwhash - GenerateNTResponse() - RFC 2759, Sect. 8.1 - * @auth_challenge: 16-octet AuthenticatorChallenge (IN) - * @peer_hallenge: 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) - */ -void 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]; - - challenge_hash(peer_challenge, auth_challenge, username, username_len, - challenge); - challenge_response(challenge, password_hash, response); -} - - -/** - * 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>) - */ -void 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; - - hash_nt_password_hash(password_hash, password_hash_hash); - sha1_vector(3, addr1, len1, response); - - challenge_hash(peer_challenge, auth_challenge, username, username_len, - challenge); - 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>) - */ -void 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]; - nt_password_hash(password, password_len, password_hash); - 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) - */ -void nt_challenge_response(const u8 *challenge, const u8 *password, - size_t password_len, u8 *response) -{ - u8 password_hash[16]; - nt_password_hash(password, password_len, password_hash); - challenge_response(challenge, password_hash, response); -} - - -/** - * 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) - */ -void 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; - - sha1_vector(3, addr, len, hash); - os_memcpy(master_key, hash, 16); -} - - -/** - * 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) - */ -void 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; - - sha1_vector(4, addr, len, digest); - - if (session_key_len > SHA1_MAC_LEN) - session_key_len = SHA1_MAC_LEN; - os_memcpy(session_key, digest, session_key_len); -} - - -#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) - */ -static void 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; - - os_memset(pw_block, 0, PWBLOCK_LEN); - offset = (256 - password_len) * 2; - os_get_random(pw_block, offset); - 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(pw_block, PWBLOCK_LEN, password_hash, 16); -} - - -/** - * 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) - */ -void 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]; - - nt_password_hash(old_password, old_password_len, password_hash); - encrypt_pw_block_with_password_hash(new_password, new_password_len, - password_hash, encrypted_pw_block); -} - - -/** - * 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) - */ -static 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_ash: 16-octet EncryptedPasswordHash (OUT) - */ -void 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]; - - nt_password_hash(old_password, old_password_len, old_password_hash); - nt_password_hash(new_password, new_password_len, new_password_hash); - nt_password_hash_encrypted_with_block(old_password_hash, - new_password_hash, - encrypted_password_hash); -} diff --git a/contrib/wpa_supplicant/ms_funcs.h b/contrib/wpa_supplicant/ms_funcs.h deleted file mode 100644 index 8067c097214a..000000000000 --- a/contrib/wpa_supplicant/ms_funcs.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * WPA Supplicant / shared MSCHAPV2 helper functions / RFC 2433 / RFC 2759 - * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 - -void 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); -void 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); -void 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); -void 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); -void 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); -void nt_password_hash(const u8 *password, size_t password_len, - u8 *password_hash); -void hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash); -void get_master_key(const u8 *password_hash_hash, const u8 *nt_response, - u8 *master_key); -void get_asymetric_start_key(const u8 *master_key, u8 *session_key, - size_t session_key_len, int is_send, - int is_server); -void 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 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/contrib/wpa_supplicant/nmake.mak b/contrib/wpa_supplicant/nmake.mak deleted file mode 100644 index 3afabadeb9b5..000000000000 --- a/contrib/wpa_supplicant/nmake.mak +++ /dev/null @@ -1,188 +0,0 @@ -# Makefile for Microsoft nmake to build wpa_supplicant - -# This can be run in Visual Studio 2005 Command Prompt - -# Note: Make sure that cl.exe is configured to include Platform SDK -# include and lib directories (vsvars32.bat) - -all: wpa_supplicant.exe wpa_cli.exe wpa_passphrase.exe wpasvc.exe win_if_list.exe - -# Root directory for WinPcap developer's pack -# (http://www.winpcap.org/install/bin/WpdPack_3_1.zip) -WINPCAPDIR=C:\dev\WpdPack - -# Root directory for OpenSSL -# (http://www.openssl.org/source/openssl-0.9.8a.tar.gz) -# Build and installed following instructions in INSTALL.W32 -# Note: If EAP-FAST is included in the build, OpenSSL needs to be patched to -# support it (openssl-tls-extensions.patch) -# Alternatively, see README-Windows.txt for information about binary -# installation package for OpenSSL. -OPENSSLDIR=C:\dev\openssl - -CC = cl -OBJDIR = objs - -CFLAGS = /DCONFIG_NATIVE_WINDOWS -CFLAGS = $(CFLAGS) /DCONFIG_NDIS_EVENTS_INTEGRATED -CFLAGS = $(CFLAGS) /DCONFIG_ANSI_C_EXTRA -CFLAGS = $(CFLAGS) /DCONFIG_WINPCAP -CFLAGS = $(CFLAGS) /DIEEE8021X_EAPOL -CFLAGS = $(CFLAGS) /DEAP_TLS_FUNCS -CFLAGS = $(CFLAGS) /DPKCS12_FUNCS -CFLAGS = $(CFLAGS) /DEAP_MD5 -CFLAGS = $(CFLAGS) /DEAP_TLS -CFLAGS = $(CFLAGS) /DEAP_MSCHAPv2 -CFLAGS = $(CFLAGS) /DEAP_PEAP -CFLAGS = $(CFLAGS) /DEAP_TTLS -CFLAGS = $(CFLAGS) /DEAP_GTC -CFLAGS = $(CFLAGS) /DEAP_OTP -CFLAGS = $(CFLAGS) /DEAP_SIM -CFLAGS = $(CFLAGS) /DEAP_LEAP -CFLAGS = $(CFLAGS) /DEAP_PSK -CFLAGS = $(CFLAGS) /DEAP_AKA -#CFLAGS = $(CFLAGS) /DEAP_FAST -CFLAGS = $(CFLAGS) /DEAP_PAX -CFLAGS = $(CFLAGS) /DPCSC_FUNCS -CFLAGS = $(CFLAGS) /DCONFIG_CTRL_IFACE -CFLAGS = $(CFLAGS) /DCONFIG_CTRL_IFACE_NAMED_PIPE -CFLAGS = $(CFLAGS) /DCONFIG_DRIVER_NDIS -CFLAGS = $(CFLAGS) /I..\hostapd /I. -CFLAGS = $(CFLAGS) /DWIN32 -CFLAGS = $(CFLAGS) /Fo$(OBJDIR)\\ /c -CFLAGS = $(CFLAGS) /W3 - -#CFLAGS = $(CFLAGS) /WX - -# VS 2005 complains about lot of deprecated string functions; let's ignore them -# at least for now since snprintf and strncpy can be used in a safe way -CFLAGS = $(CFLAGS) /D_CRT_SECURE_NO_DEPRECATE - -OBJS = \ - $(OBJDIR)\os_win32.obj \ - $(OBJDIR)\eloop_win.obj \ - $(OBJDIR)\sha1.obj \ - $(OBJDIR)\md5.obj \ - $(OBJDIR)\rc4.obj \ - $(OBJDIR)\aes_wrap.obj \ - $(OBJDIR)\common.obj \ - $(OBJDIR)\wpa_supplicant.obj \ - $(OBJDIR)\wpa.obj \ - $(OBJDIR)\preauth.obj \ - $(OBJDIR)\pmksa_cache.obj \ - $(OBJDIR)\eapol_sm.obj \ - $(OBJDIR)\eap.obj \ - $(OBJDIR)\eap_methods.obj \ - $(OBJDIR)\eap_tlv.obj \ - $(OBJDIR)\eap_md5.obj \ - $(OBJDIR)\eap_tls.obj \ - $(OBJDIR)\eap_tls_common.obj \ - $(OBJDIR)\eap_mschapv2.obj \ - $(OBJDIR)\eap_peap.obj \ - $(OBJDIR)\eap_ttls.obj \ - $(OBJDIR)\eap_gtc.obj \ - $(OBJDIR)\eap_otp.obj \ - $(OBJDIR)\eap_leap.obj \ - $(OBJDIR)\eap_sim.obj \ - $(OBJDIR)\eap_sim_common.obj \ - $(OBJDIR)\eap_aka.obj \ - $(OBJDIR)\eap_pax.obj \ - $(OBJDIR)\eap_pax_common.obj \ - $(OBJDIR)\eap_psk.obj \ - $(OBJDIR)\eap_psk_common.obj \ - $(OBJDIR)\ctrl_iface.obj \ - $(OBJDIR)\ctrl_iface_named_pipe.obj \ - $(OBJDIR)\driver_ndis.obj \ - $(OBJDIR)\driver_ndis_.obj \ - $(OBJDIR)\events.obj \ - $(OBJDIR)\config.obj \ - $(OBJDIR)\l2_packet_winpcap.obj \ - $(OBJDIR)\tls_openssl.obj \ - $(OBJDIR)\ms_funcs.obj \ - $(OBJDIR)\crypto.obj \ - $(OBJDIR)\pcsc_funcs.obj \ - $(OBJDIR)\ndis_events.obj - -# OBJS = $(OBJS) $(OBJDIR)\eap_fast.obj - -OBJS_t = $(OBJS) \ - $(OBJDIR)\eapol_test.obj \ - $(OBJDIR)\radius.obj \ - $(OBJDIR)\radius_client.obj \ - $(OBJDIR)\config_file.obj $(OBJDIR)\base64.obj - -OBJS_t2 = $(OBJS) \ - $(OBJDIR)\preauth_test.obj \ - $(OBJDIR)\config_file.obj $(OBJDIR)\base64.obj - -OBJS2 = $(OBJDIR)\drivers.obj \ - $(OBJDIR)\config_file.obj $(OBJDIR)\base64.obj \ - $(OBJS2) $(OBJDIR)\main.obj - -OBJS3 = $(OBJDIR)\drivers.obj \ - $(OBJDIR)\config_winreg.obj \ - $(OBJS3) $(OBJDIR)\main_winsvc.obj - -OBJS_c = \ - $(OBJDIR)\os_win32.obj \ - $(OBJDIR)\wpa_cli.obj \ - $(OBJDIR)\wpa_ctrl.obj \ - $(OBJDIR)\common.obj - -OBJS_p = \ - $(OBJDIR)\os_win32.obj \ - $(OBJDIR)\common.obj \ - $(OBJDIR)\sha1.obj \ - $(OBJDIR)\md5.obj \ - $(OBJDIR)\crypto.obj \ - $(OBJDIR)\wpa_passphrase.obj - -LIBS = wbemuuid.lib libcmt.lib kernel32.lib uuid.lib ole32.lib oleaut32.lib \ - ws2_32.lib Advapi32.lib Crypt32.lib Winscard.lib \ - Packet.lib wpcap.lib \ - libeay32.lib ssleay32.lib -# If using Win32 OpenSSL binary installation from Shining Light Productions, -# replace the last line with this for dynamic libraries -# libeay32MT.lib ssleay32MT.lib -# and this for static libraries -# libeay32MT.lib ssleay32MT.lib Gdi32.lib User32.lib - -CFLAGS = $(CFLAGS) /I"$(WINPCAPDIR)/Include" /I"$(OPENSSLDIR)\include" -LFLAGS = /libpath:"$(WINPCAPDIR)\Lib" /libpath:"$(OPENSSLDIR)\lib" - -wpa_supplicant.exe: $(OBJDIR) $(OBJS) $(OBJS2) - link.exe /out:wpa_supplicant.exe $(LFLAGS) $(OBJS) $(OBJS2) $(LIBS) - -wpasvc.exe: $(OBJDIR) $(OBJS) $(OBJS3) - link.exe /out:wpasvc.exe $(LFLAGS) $(OBJS) $(OBJS3) $(LIBS) - -wpa_cli.exe: $(OBJDIR) $(OBJS_c) - link.exe /out:wpa_cli.exe $(LFLAGS) $(OBJS_c) $(LIBS) - -wpa_passphrase.exe: $(OBJDIR) $(OBJS_p) - link.exe /out:wpa_passphrase.exe $(LFLAGS) $(OBJS_p) $(LIBS) - -eapol_test.exe: $(OBJDIR) $(OBJS_t) - link.exe /out:eapol_test.exe $(LFLAGS) $(OBJS_t) $(LIBS) - -preauth_test.exe: $(OBJDIR) $(OBJS_t2) - link.exe /out:preauth_test.exe $(LFLAGS) $(OBJS_t2) $(LIBS) - -win_if_list.exe: $(OBJDIR) $(OBJDIR)\win_if_list.obj - link.exe /out:win_if_list.exe $(LFLAGS) $(OBJDIR)\win_if_list.obj $(LIBS) - - -{..\hostapd}.c{$(OBJDIR)}.obj:: - $(CC) $(CFLAGS) $< - -{.\}.c{$(OBJDIR)}.obj:: - $(CC) $(CFLAGS) $< - -{.\}.cpp{$(OBJDIR)}.obj:: - $(CC) $(CFLAGS) $< - -$(OBJDIR): - if not exist "$(OBJDIR)" mkdir "$(OBJDIR)" - -clean: - erase $(OBJDIR)\*.obj wpa_supplicant.exe diff --git a/contrib/wpa_supplicant/openssl-0.9.8d-tls-extensions.patch b/contrib/wpa_supplicant/openssl-0.9.8d-tls-extensions.patch deleted file mode 100644 index eec6db8a1341..000000000000 --- a/contrib/wpa_supplicant/openssl-0.9.8d-tls-extensions.patch +++ /dev/null @@ -1,429 +0,0 @@ -This patch is adding support for TLS hello extensions and externally -generated pre-shared key material to OpenSSL 0.9.8d. This is -based on the patch from Alexey Kobozev <akobozev@cisco.com> -(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300). - - - -diff -uprN openssl-0.9.8d.orig/include/openssl/ssl.h openssl-0.9.8d/include/openssl/ssl.h ---- openssl-0.9.8d.orig/include/openssl/ssl.h 2006-06-14 06:52:49.000000000 -0700 -+++ openssl-0.9.8d/include/openssl/ssl.h 2006-12-10 08:20:02.000000000 -0800 -@@ -345,6 +345,7 @@ extern "C" { - * 'struct ssl_st *' function parameters used to prototype callbacks - * in SSL_CTX. */ - typedef struct ssl_st *ssl_crock_st; -+typedef struct tls_extension_st TLS_EXTENSION; - - /* used to hold info on the particular ciphers used */ - typedef struct ssl_cipher_st -@@ -366,6 +367,8 @@ DECLARE_STACK_OF(SSL_CIPHER) - typedef struct ssl_st SSL; - typedef struct ssl_ctx_st SSL_CTX; - -+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg); -+ - /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */ - typedef struct ssl_method_st - { -@@ -973,6 +976,15 @@ struct ssl_st - int first_packet; - int client_version; /* what was passed, used for - * SSLv3/TLS rollback check */ -+ -+ /* TLS externsions */ -+ TLS_EXTENSION *tls_extension; -+ int (*tls_extension_cb)(SSL *s, TLS_EXTENSION *tls_ext, void *arg); -+ void *tls_extension_cb_arg; -+ -+ /* TLS pre-shared secret session resumption */ -+ tls_session_secret_cb_fn tls_session_secret_cb; -+ void *tls_session_secret_cb_arg; - }; - - #ifdef __cplusplus -@@ -1538,6 +1550,13 @@ void *SSL_COMP_get_compression_methods(v - int SSL_COMP_add_compression_method(int id,void *cm); - #endif - -+/* TLS extensions functions */ -+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len); -+int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg); -+ -+/* Pre-shared secret session resumption functions */ -+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg); -+ - /* BEGIN ERROR CODES */ - /* The following lines are auto generated by the script mkerr.pl. Any changes - * made after this point may be overwritten when the script is next run. -@@ -1719,6 +1738,7 @@ void ERR_load_SSL_strings(void); - #define SSL_F_TLS1_ENC 210 - #define SSL_F_TLS1_SETUP_KEY_BLOCK 211 - #define SSL_F_WRITE_PENDING 212 -+#define SSL_F_SSL_SET_HELLO_EXTENSION 213 - - /* Reason codes. */ - #define SSL_R_APP_DATA_IN_HANDSHAKE 100 -diff -uprN openssl-0.9.8d.orig/include/openssl/tls1.h openssl-0.9.8d/include/openssl/tls1.h ---- openssl-0.9.8d.orig/include/openssl/tls1.h 2006-06-14 10:52:01.000000000 -0700 -+++ openssl-0.9.8d/include/openssl/tls1.h 2006-12-10 08:20:02.000000000 -0800 -@@ -296,6 +296,14 @@ extern "C" { - #define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/ - #endif - -+/* TLS extension struct */ -+struct tls_extension_st -+{ -+ unsigned short type; -+ unsigned short length; -+ void *data; -+}; -+ - #ifdef __cplusplus - } - #endif -diff -uprN openssl-0.9.8d.orig/ssl/Makefile openssl-0.9.8d/ssl/Makefile ---- openssl-0.9.8d.orig/ssl/Makefile 2006-02-03 17:49:35.000000000 -0800 -+++ openssl-0.9.8d/ssl/Makefile 2006-12-10 08:20:02.000000000 -0800 -@@ -24,7 +24,7 @@ LIBSRC= \ - s2_meth.c s2_srvr.c s2_clnt.c s2_lib.c s2_enc.c s2_pkt.c \ - s3_meth.c s3_srvr.c s3_clnt.c s3_lib.c s3_enc.c s3_pkt.c s3_both.c \ - s23_meth.c s23_srvr.c s23_clnt.c s23_lib.c s23_pkt.c \ -- t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c \ -+ t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c t1_ext.c \ - d1_meth.c d1_srvr.c d1_clnt.c d1_lib.c d1_pkt.c \ - d1_both.c d1_enc.c \ - ssl_lib.c ssl_err2.c ssl_cert.c ssl_sess.c \ -@@ -35,7 +35,7 @@ LIBOBJ= \ - s2_meth.o s2_srvr.o s2_clnt.o s2_lib.o s2_enc.o s2_pkt.o \ - s3_meth.o s3_srvr.o s3_clnt.o s3_lib.o s3_enc.o s3_pkt.o s3_both.o \ - s23_meth.o s23_srvr.o s23_clnt.o s23_lib.o s23_pkt.o \ -- t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o \ -+ t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o t1_ext.o \ - d1_meth.o d1_srvr.o d1_clnt.o d1_lib.o d1_pkt.o \ - d1_both.o d1_enc.o \ - ssl_lib.o ssl_err2.o ssl_cert.o ssl_sess.o \ -@@ -968,3 +968,4 @@ t1_srvr.o: ../include/openssl/ssl23.h .. - t1_srvr.o: ../include/openssl/stack.h ../include/openssl/symhacks.h - t1_srvr.o: ../include/openssl/tls1.h ../include/openssl/x509.h - t1_srvr.o: ../include/openssl/x509_vfy.h ssl_locl.h t1_srvr.c -+t1_ext.o: t1_ext.c ssl_locl.h -diff -uprN openssl-0.9.8d.orig/ssl/s3_clnt.c openssl-0.9.8d/ssl/s3_clnt.c ---- openssl-0.9.8d.orig/ssl/s3_clnt.c 2005-12-12 23:41:46.000000000 -0800 -+++ openssl-0.9.8d/ssl/s3_clnt.c 2006-12-10 08:20:02.000000000 -0800 -@@ -601,6 +601,20 @@ int ssl3_client_hello(SSL *s) - #endif - *(p++)=0; /* Add the NULL method */ - -+ /* send client hello extensions if any */ -+ if (s->version >= TLS1_VERSION && s->tls_extension) -+ { -+ // set the total extensions length -+ s2n(s->tls_extension->length + 4, p); -+ -+ // put the extensions with type and length -+ s2n(s->tls_extension->type, p); -+ s2n(s->tls_extension->length, p); -+ -+ memcpy(p, s->tls_extension->data, s->tls_extension->length); -+ p+=s->tls_extension->length; -+ } -+ - l=(p-d); - d=buf; - *(d++)=SSL3_MT_CLIENT_HELLO; -@@ -623,7 +637,7 @@ int ssl3_get_server_hello(SSL *s) - STACK_OF(SSL_CIPHER) *sk; - SSL_CIPHER *c; - unsigned char *p,*d; -- int i,al,ok; -+ int i,al,ok,pre_shared; - unsigned int j; - long n; - #ifndef OPENSSL_NO_COMP -@@ -690,7 +704,24 @@ int ssl3_get_server_hello(SSL *s) - goto f_err; - } - -- if (j != 0 && j == s->session->session_id_length -+ /* check if we want to resume the session based on external pre-shared secret */ -+ pre_shared = 0; -+ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb) -+ { -+ SSL_CIPHER *pref_cipher=NULL; -+ s->session->master_key_length=sizeof(s->session->master_key); -+ if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, -+ NULL, &pref_cipher, s->tls_session_secret_cb_arg)) -+ { -+ s->hit=1; -+ s->session->cipher=pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s,p+j); -+ s->session->session_id_length = j; -+ memcpy(s->session->session_id, p, j); -+ pre_shared = 1; -+ } -+ } -+ -+ if ((pre_shared || j != 0) && j == s->session->session_id_length - && memcmp(p,s->session->session_id,j) == 0) - { - if(s->sid_ctx_length != s->session->sid_ctx_length -diff -uprN openssl-0.9.8d.orig/ssl/s3_srvr.c openssl-0.9.8d/ssl/s3_srvr.c ---- openssl-0.9.8d.orig/ssl/s3_srvr.c 2006-09-28 04:29:03.000000000 -0700 -+++ openssl-0.9.8d/ssl/s3_srvr.c 2006-12-10 08:20:02.000000000 -0800 -@@ -943,6 +943,75 @@ int ssl3_get_client_hello(SSL *s) - } - #endif - -+ /* Check for TLS client hello extension here */ -+ if (p < (d+n) && s->version >= TLS1_VERSION) -+ { -+ if (s->tls_extension_cb) -+ { -+ TLS_EXTENSION tls_ext; -+ unsigned short ext_total_len; -+ -+ n2s(p, ext_total_len); -+ n2s(p, tls_ext.type); -+ n2s(p, tls_ext.length); -+ -+ // sanity check in TLS extension len -+ if (tls_ext.length > (d+n) - p) -+ { -+ // just cut the lenth to packet border -+ tls_ext.length = (d+n) - p; -+ } -+ -+ tls_ext.data = p; -+ -+ // returns an alert code or 0 -+ al = s->tls_extension_cb(s, &tls_ext, s->tls_extension_cb_arg); -+ if (al != 0) -+ { -+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_PEER_ERROR); -+ goto f_err; -+ } -+ } -+ } -+ -+ /* Check if we want to use external pre-shared secret for this handshake */ -+ /* for not reused session only */ -+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb) -+ { -+ SSL_CIPHER *pref_cipher=NULL; -+ -+ s->session->master_key_length=sizeof(s->session->master_key); -+ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, -+ ciphers, &pref_cipher, s->tls_session_secret_cb_arg)) -+ { -+ s->hit=1; -+ s->session->ciphers=ciphers; -+ s->session->verify_result=X509_V_OK; -+ -+ ciphers=NULL; -+ -+ /* check if some cipher was preferred by call back */ -+ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s)); -+ if (pref_cipher == NULL) -+ { -+ al=SSL_AD_HANDSHAKE_FAILURE; -+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER); -+ goto f_err; -+ } -+ -+ s->session->cipher=pref_cipher; -+ -+ if (s->cipher_list) -+ sk_SSL_CIPHER_free(s->cipher_list); -+ -+ if (s->cipher_list_by_id) -+ sk_SSL_CIPHER_free(s->cipher_list_by_id); -+ -+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers); -+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers); -+ } -+ } -+ - /* Given s->session->ciphers and SSL_get_ciphers, we must - * pick a cipher */ - -diff -uprN openssl-0.9.8d.orig/ssl/ssl.h openssl-0.9.8d/ssl/ssl.h ---- openssl-0.9.8d.orig/ssl/ssl.h 2006-06-14 06:52:49.000000000 -0700 -+++ openssl-0.9.8d/ssl/ssl.h 2006-12-10 08:20:02.000000000 -0800 -@@ -345,6 +345,7 @@ extern "C" { - * 'struct ssl_st *' function parameters used to prototype callbacks - * in SSL_CTX. */ - typedef struct ssl_st *ssl_crock_st; -+typedef struct tls_extension_st TLS_EXTENSION; - - /* used to hold info on the particular ciphers used */ - typedef struct ssl_cipher_st -@@ -366,6 +367,8 @@ DECLARE_STACK_OF(SSL_CIPHER) - typedef struct ssl_st SSL; - typedef struct ssl_ctx_st SSL_CTX; - -+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg); -+ - /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */ - typedef struct ssl_method_st - { -@@ -973,6 +976,15 @@ struct ssl_st - int first_packet; - int client_version; /* what was passed, used for - * SSLv3/TLS rollback check */ -+ -+ /* TLS externsions */ -+ TLS_EXTENSION *tls_extension; -+ int (*tls_extension_cb)(SSL *s, TLS_EXTENSION *tls_ext, void *arg); -+ void *tls_extension_cb_arg; -+ -+ /* TLS pre-shared secret session resumption */ -+ tls_session_secret_cb_fn tls_session_secret_cb; -+ void *tls_session_secret_cb_arg; - }; - - #ifdef __cplusplus -@@ -1538,6 +1550,13 @@ void *SSL_COMP_get_compression_methods(v - int SSL_COMP_add_compression_method(int id,void *cm); - #endif - -+/* TLS extensions functions */ -+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len); -+int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg); -+ -+/* Pre-shared secret session resumption functions */ -+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg); -+ - /* BEGIN ERROR CODES */ - /* The following lines are auto generated by the script mkerr.pl. Any changes - * made after this point may be overwritten when the script is next run. -@@ -1719,6 +1738,7 @@ void ERR_load_SSL_strings(void); - #define SSL_F_TLS1_ENC 210 - #define SSL_F_TLS1_SETUP_KEY_BLOCK 211 - #define SSL_F_WRITE_PENDING 212 -+#define SSL_F_SSL_SET_HELLO_EXTENSION 213 - - /* Reason codes. */ - #define SSL_R_APP_DATA_IN_HANDSHAKE 100 -diff -uprN openssl-0.9.8d.orig/ssl/ssl_err.c openssl-0.9.8d/ssl/ssl_err.c ---- openssl-0.9.8d.orig/ssl/ssl_err.c 2006-01-08 13:52:46.000000000 -0800 -+++ openssl-0.9.8d/ssl/ssl_err.c 2006-12-10 08:20:02.000000000 -0800 -@@ -242,6 +242,7 @@ static ERR_STRING_DATA SSL_str_functs[]= - {ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"}, - {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"}, - {ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"}, -+{ERR_FUNC(SSL_F_SSL_SET_HELLO_EXTENSION), "SSL_set_hello_extension"}, - {0,NULL} - }; - -diff -uprN openssl-0.9.8d.orig/ssl/ssl_sess.c openssl-0.9.8d/ssl/ssl_sess.c ---- openssl-0.9.8d.orig/ssl/ssl_sess.c 2005-12-30 15:51:57.000000000 -0800 -+++ openssl-0.9.8d/ssl/ssl_sess.c 2006-12-10 08:20:02.000000000 -0800 -@@ -656,6 +656,15 @@ long SSL_CTX_get_timeout(const SSL_CTX * - return(s->session_timeout); - } - -+int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len, -+ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg) -+{ -+ if (s == NULL) return(0); -+ s->tls_session_secret_cb = tls_session_secret_cb; -+ s->tls_session_secret_cb_arg = arg; -+ return(1); -+} -+ - typedef struct timeout_param_st - { - SSL_CTX *ctx; -diff -uprN openssl-0.9.8d.orig/ssl/t1_ext.c openssl-0.9.8d/ssl/t1_ext.c ---- openssl-0.9.8d.orig/ssl/t1_ext.c 1969-12-31 16:00:00.000000000 -0800 -+++ openssl-0.9.8d/ssl/t1_ext.c 2006-12-10 08:20:02.000000000 -0800 -@@ -0,0 +1,48 @@ -+ -+#include <stdio.h> -+#include "ssl_locl.h" -+ -+ -+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len) -+{ -+ if(s->version >= TLS1_VERSION) -+ { -+ if(s->tls_extension) -+ { -+ OPENSSL_free(s->tls_extension); -+ s->tls_extension = NULL; -+ } -+ -+ if(ext_data) -+ { -+ s->tls_extension = OPENSSL_malloc(sizeof(TLS_EXTENSION) + ext_len); -+ if(!s->tls_extension) -+ { -+ SSLerr(SSL_F_SSL_SET_HELLO_EXTENSION, ERR_R_MALLOC_FAILURE); -+ return 0; -+ } -+ -+ s->tls_extension->type = ext_type; -+ s->tls_extension->length = ext_len; -+ s->tls_extension->data = s->tls_extension + 1; -+ memcpy(s->tls_extension->data, ext_data, ext_len); -+ } -+ -+ return 1; -+ } -+ -+ return 0; -+} -+ -+int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg) -+{ -+ if(s->version >= TLS1_VERSION) -+ { -+ s->tls_extension_cb = cb; -+ s->tls_extension_cb_arg = arg; -+ -+ return 1; -+ } -+ -+ return 0; -+} -diff -uprN openssl-0.9.8d.orig/ssl/t1_lib.c openssl-0.9.8d/ssl/t1_lib.c ---- openssl-0.9.8d.orig/ssl/t1_lib.c 2005-08-05 16:52:07.000000000 -0700 -+++ openssl-0.9.8d/ssl/t1_lib.c 2006-12-10 08:20:02.000000000 -0800 -@@ -97,6 +97,10 @@ int tls1_new(SSL *s) - - void tls1_free(SSL *s) - { -+ if(s->tls_extension) -+ { -+ OPENSSL_free(s->tls_extension); -+ } - ssl3_free(s); - } - -diff -uprN openssl-0.9.8d.orig/ssl/tls1.h openssl-0.9.8d/ssl/tls1.h ---- openssl-0.9.8d.orig/ssl/tls1.h 2006-06-14 10:52:01.000000000 -0700 -+++ openssl-0.9.8d/ssl/tls1.h 2006-12-10 08:20:02.000000000 -0800 -@@ -296,6 +296,14 @@ extern "C" { - #define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/ - #endif - -+/* TLS extension struct */ -+struct tls_extension_st -+{ -+ unsigned short type; -+ unsigned short length; -+ void *data; -+}; -+ - #ifdef __cplusplus - } - #endif -diff -uprN openssl-0.9.8d.orig/util/ssleay.num openssl-0.9.8d/util/ssleay.num ---- openssl-0.9.8d.orig/util/ssleay.num 2005-05-08 17:22:02.000000000 -0700 -+++ openssl-0.9.8d/util/ssleay.num 2006-12-10 08:20:02.000000000 -0800 -@@ -226,3 +226,6 @@ DTLSv1_server_method - SSL_COMP_get_compression_methods 276 EXIST:!VMS:FUNCTION:COMP - SSL_COMP_get_compress_methods 276 EXIST:VMS:FUNCTION:COMP - SSL_SESSION_get_id 277 EXIST::FUNCTION: -+SSL_set_hello_extension 278 EXIST::FUNCTION: -+SSL_set_hello_extension_cb 279 EXIST::FUNCTION: -+SSL_set_session_secret_cb 280 EXIST::FUNCTION: diff --git a/contrib/wpa_supplicant/openssl-0.9.8e-tls-extensions.patch b/contrib/wpa_supplicant/openssl-0.9.8e-tls-extensions.patch deleted file mode 100644 index ede053f779b6..000000000000 --- a/contrib/wpa_supplicant/openssl-0.9.8e-tls-extensions.patch +++ /dev/null @@ -1,353 +0,0 @@ -This patch is adding support for TLS hello extensions and externally -generated pre-shared key material to OpenSSL 0.9.8e. This is -based on the patch from Alexey Kobozev <akobozev@cisco.com> -(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300). - - - -diff -uprN openssl-0.9.8e.orig/ssl/Makefile openssl-0.9.8e/ssl/Makefile ---- openssl-0.9.8e.orig/ssl/Makefile 2006-02-03 17:49:35.000000000 -0800 -+++ openssl-0.9.8e/ssl/Makefile 2007-03-22 20:23:19.000000000 -0700 -@@ -24,7 +24,7 @@ LIBSRC= \ - s2_meth.c s2_srvr.c s2_clnt.c s2_lib.c s2_enc.c s2_pkt.c \ - s3_meth.c s3_srvr.c s3_clnt.c s3_lib.c s3_enc.c s3_pkt.c s3_both.c \ - s23_meth.c s23_srvr.c s23_clnt.c s23_lib.c s23_pkt.c \ -- t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c \ -+ t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c t1_ext.c \ - d1_meth.c d1_srvr.c d1_clnt.c d1_lib.c d1_pkt.c \ - d1_both.c d1_enc.c \ - ssl_lib.c ssl_err2.c ssl_cert.c ssl_sess.c \ -@@ -35,7 +35,7 @@ LIBOBJ= \ - s2_meth.o s2_srvr.o s2_clnt.o s2_lib.o s2_enc.o s2_pkt.o \ - s3_meth.o s3_srvr.o s3_clnt.o s3_lib.o s3_enc.o s3_pkt.o s3_both.o \ - s23_meth.o s23_srvr.o s23_clnt.o s23_lib.o s23_pkt.o \ -- t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o \ -+ t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o t1_ext.o \ - d1_meth.o d1_srvr.o d1_clnt.o d1_lib.o d1_pkt.o \ - d1_both.o d1_enc.o \ - ssl_lib.o ssl_err2.o ssl_cert.o ssl_sess.o \ -@@ -968,3 +968,4 @@ t1_srvr.o: ../include/openssl/ssl23.h .. - t1_srvr.o: ../include/openssl/stack.h ../include/openssl/symhacks.h - t1_srvr.o: ../include/openssl/tls1.h ../include/openssl/x509.h - t1_srvr.o: ../include/openssl/x509_vfy.h ssl_locl.h t1_srvr.c -+t1_ext.o: t1_ext.c ssl_locl.h -diff -uprN openssl-0.9.8e.orig/ssl/s3_clnt.c openssl-0.9.8e/ssl/s3_clnt.c ---- openssl-0.9.8e.orig/ssl/s3_clnt.c 2006-09-28 05:23:15.000000000 -0700 -+++ openssl-0.9.8e/ssl/s3_clnt.c 2007-03-22 20:23:19.000000000 -0700 -@@ -601,6 +601,20 @@ int ssl3_client_hello(SSL *s) - #endif - *(p++)=0; /* Add the NULL method */ - -+ /* send client hello extensions if any */ -+ if (s->version >= TLS1_VERSION && s->tls_extension) -+ { -+ // set the total extensions length -+ s2n(s->tls_extension->length + 4, p); -+ -+ // put the extensions with type and length -+ s2n(s->tls_extension->type, p); -+ s2n(s->tls_extension->length, p); -+ -+ memcpy(p, s->tls_extension->data, s->tls_extension->length); -+ p+=s->tls_extension->length; -+ } -+ - l=(p-d); - d=buf; - *(d++)=SSL3_MT_CLIENT_HELLO; -@@ -623,7 +637,7 @@ int ssl3_get_server_hello(SSL *s) - STACK_OF(SSL_CIPHER) *sk; - SSL_CIPHER *c; - unsigned char *p,*d; -- int i,al,ok; -+ int i,al,ok,pre_shared; - unsigned int j; - long n; - #ifndef OPENSSL_NO_COMP -@@ -690,7 +704,24 @@ int ssl3_get_server_hello(SSL *s) - goto f_err; - } - -- if (j != 0 && j == s->session->session_id_length -+ /* check if we want to resume the session based on external pre-shared secret */ -+ pre_shared = 0; -+ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb) -+ { -+ SSL_CIPHER *pref_cipher=NULL; -+ s->session->master_key_length=sizeof(s->session->master_key); -+ if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, -+ NULL, &pref_cipher, s->tls_session_secret_cb_arg)) -+ { -+ s->hit=1; -+ s->session->cipher=pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s,p+j); -+ s->session->session_id_length = j; -+ memcpy(s->session->session_id, p, j); -+ pre_shared = 1; -+ } -+ } -+ -+ if ((pre_shared || j != 0) && j == s->session->session_id_length - && memcmp(p,s->session->session_id,j) == 0) - { - if(s->sid_ctx_length != s->session->sid_ctx_length -diff -uprN openssl-0.9.8e.orig/ssl/s3_srvr.c openssl-0.9.8e/ssl/s3_srvr.c ---- openssl-0.9.8e.orig/ssl/s3_srvr.c 2007-02-07 12:36:40.000000000 -0800 -+++ openssl-0.9.8e/ssl/s3_srvr.c 2007-03-22 20:23:19.000000000 -0700 -@@ -945,6 +945,75 @@ int ssl3_get_client_hello(SSL *s) - } - #endif - -+ /* Check for TLS client hello extension here */ -+ if (p < (d+n) && s->version >= TLS1_VERSION) -+ { -+ if (s->tls_extension_cb) -+ { -+ TLS_EXTENSION tls_ext; -+ unsigned short ext_total_len; -+ -+ n2s(p, ext_total_len); -+ n2s(p, tls_ext.type); -+ n2s(p, tls_ext.length); -+ -+ // sanity check in TLS extension len -+ if (tls_ext.length > (d+n) - p) -+ { -+ // just cut the lenth to packet border -+ tls_ext.length = (d+n) - p; -+ } -+ -+ tls_ext.data = p; -+ -+ // returns an alert code or 0 -+ al = s->tls_extension_cb(s, &tls_ext, s->tls_extension_cb_arg); -+ if (al != 0) -+ { -+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_PEER_ERROR); -+ goto f_err; -+ } -+ } -+ } -+ -+ /* Check if we want to use external pre-shared secret for this handshake */ -+ /* for not reused session only */ -+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb) -+ { -+ SSL_CIPHER *pref_cipher=NULL; -+ -+ s->session->master_key_length=sizeof(s->session->master_key); -+ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, -+ ciphers, &pref_cipher, s->tls_session_secret_cb_arg)) -+ { -+ s->hit=1; -+ s->session->ciphers=ciphers; -+ s->session->verify_result=X509_V_OK; -+ -+ ciphers=NULL; -+ -+ /* check if some cipher was preferred by call back */ -+ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s)); -+ if (pref_cipher == NULL) -+ { -+ al=SSL_AD_HANDSHAKE_FAILURE; -+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER); -+ goto f_err; -+ } -+ -+ s->session->cipher=pref_cipher; -+ -+ if (s->cipher_list) -+ sk_SSL_CIPHER_free(s->cipher_list); -+ -+ if (s->cipher_list_by_id) -+ sk_SSL_CIPHER_free(s->cipher_list_by_id); -+ -+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers); -+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers); -+ } -+ } -+ - /* Given s->session->ciphers and SSL_get_ciphers, we must - * pick a cipher */ - -diff -uprN openssl-0.9.8e.orig/ssl/ssl.h openssl-0.9.8e/ssl/ssl.h ---- openssl-0.9.8e.orig/ssl/ssl.h 2007-02-19 09:55:07.000000000 -0800 -+++ openssl-0.9.8e/ssl/ssl.h 2007-03-22 20:23:19.000000000 -0700 -@@ -345,6 +345,7 @@ extern "C" { - * 'struct ssl_st *' function parameters used to prototype callbacks - * in SSL_CTX. */ - typedef struct ssl_st *ssl_crock_st; -+typedef struct tls_extension_st TLS_EXTENSION; - - /* used to hold info on the particular ciphers used */ - typedef struct ssl_cipher_st -@@ -366,6 +367,8 @@ DECLARE_STACK_OF(SSL_CIPHER) - typedef struct ssl_st SSL; - typedef struct ssl_ctx_st SSL_CTX; - -+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg); -+ - /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */ - typedef struct ssl_method_st - { -@@ -973,6 +976,15 @@ struct ssl_st - int first_packet; - int client_version; /* what was passed, used for - * SSLv3/TLS rollback check */ -+ -+ /* TLS externsions */ -+ TLS_EXTENSION *tls_extension; -+ int (*tls_extension_cb)(SSL *s, TLS_EXTENSION *tls_ext, void *arg); -+ void *tls_extension_cb_arg; -+ -+ /* TLS pre-shared secret session resumption */ -+ tls_session_secret_cb_fn tls_session_secret_cb; -+ void *tls_session_secret_cb_arg; - }; - - #ifdef __cplusplus -@@ -1538,6 +1550,13 @@ void *SSL_COMP_get_compression_methods(v - int SSL_COMP_add_compression_method(int id,void *cm); - #endif - -+/* TLS extensions functions */ -+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len); -+int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg); -+ -+/* Pre-shared secret session resumption functions */ -+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg); -+ - /* BEGIN ERROR CODES */ - /* The following lines are auto generated by the script mkerr.pl. Any changes - * made after this point may be overwritten when the script is next run. -@@ -1719,6 +1738,7 @@ void ERR_load_SSL_strings(void); - #define SSL_F_TLS1_ENC 210 - #define SSL_F_TLS1_SETUP_KEY_BLOCK 211 - #define SSL_F_WRITE_PENDING 212 -+#define SSL_F_SSL_SET_HELLO_EXTENSION 213 - - /* Reason codes. */ - #define SSL_R_APP_DATA_IN_HANDSHAKE 100 -diff -uprN openssl-0.9.8e.orig/ssl/ssl_err.c openssl-0.9.8e/ssl/ssl_err.c ---- openssl-0.9.8e.orig/ssl/ssl_err.c 2006-11-21 12:14:46.000000000 -0800 -+++ openssl-0.9.8e/ssl/ssl_err.c 2007-03-22 20:23:19.000000000 -0700 -@@ -242,6 +242,7 @@ static ERR_STRING_DATA SSL_str_functs[]= - {ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"}, - {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"}, - {ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"}, -+{ERR_FUNC(SSL_F_SSL_SET_HELLO_EXTENSION), "SSL_set_hello_extension"}, - {0,NULL} - }; - -diff -uprN openssl-0.9.8e.orig/ssl/ssl_sess.c openssl-0.9.8e/ssl/ssl_sess.c ---- openssl-0.9.8e.orig/ssl/ssl_sess.c 2007-02-10 02:40:24.000000000 -0800 -+++ openssl-0.9.8e/ssl/ssl_sess.c 2007-03-22 20:23:19.000000000 -0700 -@@ -656,6 +656,15 @@ long SSL_CTX_get_timeout(const SSL_CTX * - return(s->session_timeout); - } - -+int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len, -+ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg) -+{ -+ if (s == NULL) return(0); -+ s->tls_session_secret_cb = tls_session_secret_cb; -+ s->tls_session_secret_cb_arg = arg; -+ return(1); -+} -+ - typedef struct timeout_param_st - { - SSL_CTX *ctx; -diff -uprN openssl-0.9.8e.orig/ssl/t1_ext.c openssl-0.9.8e/ssl/t1_ext.c ---- openssl-0.9.8e.orig/ssl/t1_ext.c 1969-12-31 16:00:00.000000000 -0800 -+++ openssl-0.9.8e/ssl/t1_ext.c 2007-03-22 20:23:19.000000000 -0700 -@@ -0,0 +1,48 @@ -+ -+#include <stdio.h> -+#include "ssl_locl.h" -+ -+ -+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len) -+{ -+ if(s->version >= TLS1_VERSION) -+ { -+ if(s->tls_extension) -+ { -+ OPENSSL_free(s->tls_extension); -+ s->tls_extension = NULL; -+ } -+ -+ if(ext_data) -+ { -+ s->tls_extension = OPENSSL_malloc(sizeof(TLS_EXTENSION) + ext_len); -+ if(!s->tls_extension) -+ { -+ SSLerr(SSL_F_SSL_SET_HELLO_EXTENSION, ERR_R_MALLOC_FAILURE); -+ return 0; -+ } -+ -+ s->tls_extension->type = ext_type; -+ s->tls_extension->length = ext_len; -+ s->tls_extension->data = s->tls_extension + 1; -+ memcpy(s->tls_extension->data, ext_data, ext_len); -+ } -+ -+ return 1; -+ } -+ -+ return 0; -+} -+ -+int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg) -+{ -+ if(s->version >= TLS1_VERSION) -+ { -+ s->tls_extension_cb = cb; -+ s->tls_extension_cb_arg = arg; -+ -+ return 1; -+ } -+ -+ return 0; -+} -diff -uprN openssl-0.9.8e.orig/ssl/t1_lib.c openssl-0.9.8e/ssl/t1_lib.c ---- openssl-0.9.8e.orig/ssl/t1_lib.c 2007-01-21 08:07:25.000000000 -0800 -+++ openssl-0.9.8e/ssl/t1_lib.c 2007-03-22 20:23:19.000000000 -0700 -@@ -97,6 +97,10 @@ int tls1_new(SSL *s) - - void tls1_free(SSL *s) - { -+ if(s->tls_extension) -+ { -+ OPENSSL_free(s->tls_extension); -+ } - ssl3_free(s); - } - -diff -uprN openssl-0.9.8e.orig/ssl/tls1.h openssl-0.9.8e/ssl/tls1.h ---- openssl-0.9.8e.orig/ssl/tls1.h 2006-06-14 10:52:01.000000000 -0700 -+++ openssl-0.9.8e/ssl/tls1.h 2007-03-22 20:23:19.000000000 -0700 -@@ -296,6 +296,14 @@ extern "C" { - #define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/ - #endif - -+/* TLS extension struct */ -+struct tls_extension_st -+{ -+ unsigned short type; -+ unsigned short length; -+ void *data; -+}; -+ - #ifdef __cplusplus - } - #endif -diff -uprN openssl-0.9.8e.orig/util/ssleay.num openssl-0.9.8e/util/ssleay.num ---- openssl-0.9.8e.orig/util/ssleay.num 2006-11-30 05:04:43.000000000 -0800 -+++ openssl-0.9.8e/util/ssleay.num 2007-03-22 20:24:07.000000000 -0700 -@@ -238,3 +238,6 @@ SSL_CTX_set_info_callback - SSL_CTX_sess_get_new_cb 287 EXIST::FUNCTION: - SSL_CTX_get_client_cert_cb 288 EXIST::FUNCTION: - SSL_CTX_sess_get_remove_cb 289 EXIST::FUNCTION: -+SSL_set_hello_extension 290 EXIST::FUNCTION: -+SSL_set_hello_extension_cb 291 EXIST::FUNCTION: -+SSL_set_session_secret_cb 292 EXIST::FUNCTION: diff --git a/contrib/wpa_supplicant/openssl-tls-extensions.patch b/contrib/wpa_supplicant/openssl-tls-extensions.patch deleted file mode 100644 index 44490cca226e..000000000000 --- a/contrib/wpa_supplicant/openssl-tls-extensions.patch +++ /dev/null @@ -1,429 +0,0 @@ -This patch is adding support for TLS hello extensions and externally -generated pre-shared key material to OpenSSL 0.9.8. This is -based on the patch from Alexey Kobozev <akobozev@cisco.com> -(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300). - - - -diff -uprN openssl-0.9.8.orig/include/openssl/ssl.h openssl-0.9.8/include/openssl/ssl.h ---- openssl-0.9.8.orig/include/openssl/ssl.h 2005-06-10 12:51:16.000000000 -0700 -+++ openssl-0.9.8/include/openssl/ssl.h 2005-07-19 20:02:15.000000000 -0700 -@@ -340,6 +340,7 @@ extern "C" { - * 'struct ssl_st *' function parameters used to prototype callbacks - * in SSL_CTX. */ - typedef struct ssl_st *ssl_crock_st; -+typedef struct tls_extension_st TLS_EXTENSION; - - /* used to hold info on the particular ciphers used */ - typedef struct ssl_cipher_st -@@ -361,6 +362,8 @@ DECLARE_STACK_OF(SSL_CIPHER) - typedef struct ssl_st SSL; - typedef struct ssl_ctx_st SSL_CTX; - -+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg); -+ - /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */ - typedef struct ssl_method_st - { -@@ -968,6 +971,15 @@ struct ssl_st - int first_packet; - int client_version; /* what was passed, used for - * SSLv3/TLS rollback check */ -+ -+ /* TLS externsions */ -+ TLS_EXTENSION *tls_extension; -+ int (*tls_extension_cb)(SSL *s, TLS_EXTENSION *tls_ext, void *arg); -+ void *tls_extension_cb_arg; -+ -+ /* TLS pre-shared secret session resumption */ -+ tls_session_secret_cb_fn tls_session_secret_cb; -+ void *tls_session_secret_cb_arg; - }; - - #ifdef __cplusplus -@@ -1533,6 +1545,13 @@ void *SSL_COMP_get_compression_methods(v - int SSL_COMP_add_compression_method(int id,void *cm); - #endif - -+/* TLS extensions functions */ -+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len); -+int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg); -+ -+/* Pre-shared secret session resumption functions */ -+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg); -+ - /* BEGIN ERROR CODES */ - /* The following lines are auto generated by the script mkerr.pl. Any changes - * made after this point may be overwritten when the script is next run. -@@ -1714,6 +1733,7 @@ void ERR_load_SSL_strings(void); - #define SSL_F_TLS1_ENC 210 - #define SSL_F_TLS1_SETUP_KEY_BLOCK 211 - #define SSL_F_WRITE_PENDING 212 -+#define SSL_F_SSL_SET_HELLO_EXTENSION 213 - - /* Reason codes. */ - #define SSL_R_APP_DATA_IN_HANDSHAKE 100 -diff -uprN openssl-0.9.8.orig/include/openssl/tls1.h openssl-0.9.8/include/openssl/tls1.h ---- openssl-0.9.8.orig/include/openssl/tls1.h 2003-07-22 05:34:21.000000000 -0700 -+++ openssl-0.9.8/include/openssl/tls1.h 2005-07-19 20:02:15.000000000 -0700 -@@ -282,6 +282,14 @@ extern "C" { - #define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/ - #endif - -+/* TLS extension struct */ -+struct tls_extension_st -+{ -+ unsigned short type; -+ unsigned short length; -+ void *data; -+}; -+ - #ifdef __cplusplus - } - #endif -diff -uprN openssl-0.9.8.orig/ssl/Makefile openssl-0.9.8/ssl/Makefile ---- openssl-0.9.8.orig/ssl/Makefile 2005-05-30 16:20:30.000000000 -0700 -+++ openssl-0.9.8/ssl/Makefile 2005-07-19 20:02:15.000000000 -0700 -@@ -24,7 +24,7 @@ LIBSRC= \ - s2_meth.c s2_srvr.c s2_clnt.c s2_lib.c s2_enc.c s2_pkt.c \ - s3_meth.c s3_srvr.c s3_clnt.c s3_lib.c s3_enc.c s3_pkt.c s3_both.c \ - s23_meth.c s23_srvr.c s23_clnt.c s23_lib.c s23_pkt.c \ -- t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c \ -+ t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c t1_ext.c \ - d1_meth.c d1_srvr.c d1_clnt.c d1_lib.c d1_pkt.c \ - d1_both.c d1_enc.c \ - ssl_lib.c ssl_err2.c ssl_cert.c ssl_sess.c \ -@@ -35,7 +35,7 @@ LIBOBJ= \ - s2_meth.o s2_srvr.o s2_clnt.o s2_lib.o s2_enc.o s2_pkt.o \ - s3_meth.o s3_srvr.o s3_clnt.o s3_lib.o s3_enc.o s3_pkt.o s3_both.o \ - s23_meth.o s23_srvr.o s23_clnt.o s23_lib.o s23_pkt.o \ -- t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o \ -+ t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o t1_ext.o \ - d1_meth.o d1_srvr.o d1_clnt.o d1_lib.o d1_pkt.o \ - d1_both.o d1_enc.o \ - ssl_lib.o ssl_err2.o ssl_cert.o ssl_sess.o \ -@@ -968,3 +968,4 @@ t1_srvr.o: ../include/openssl/ssl23.h .. - t1_srvr.o: ../include/openssl/stack.h ../include/openssl/symhacks.h - t1_srvr.o: ../include/openssl/tls1.h ../include/openssl/x509.h - t1_srvr.o: ../include/openssl/x509_vfy.h ssl_locl.h t1_srvr.c -+t1_ext.o: t1_ext.c ssl_locl.h -diff -uprN openssl-0.9.8.orig/ssl/s3_clnt.c openssl-0.9.8/ssl/s3_clnt.c ---- openssl-0.9.8.orig/ssl/s3_clnt.c 2005-05-16 03:11:03.000000000 -0700 -+++ openssl-0.9.8/ssl/s3_clnt.c 2005-07-19 20:02:15.000000000 -0700 -@@ -606,6 +606,20 @@ int ssl3_client_hello(SSL *s) - } - *(p++)=0; /* Add the NULL method */ - -+ /* send client hello extensions if any */ -+ if (s->version >= TLS1_VERSION && s->tls_extension) -+ { -+ // set the total extensions length -+ s2n(s->tls_extension->length + 4, p); -+ -+ // put the extensions with type and length -+ s2n(s->tls_extension->type, p); -+ s2n(s->tls_extension->length, p); -+ -+ memcpy(p, s->tls_extension->data, s->tls_extension->length); -+ p+=s->tls_extension->length; -+ } -+ - l=(p-d); - d=buf; - *(d++)=SSL3_MT_CLIENT_HELLO; -@@ -628,7 +642,7 @@ int ssl3_get_server_hello(SSL *s) - STACK_OF(SSL_CIPHER) *sk; - SSL_CIPHER *c; - unsigned char *p,*d; -- int i,al,ok; -+ int i,al,ok,pre_shared; - unsigned int j; - long n; - SSL_COMP *comp; -@@ -693,7 +707,24 @@ int ssl3_get_server_hello(SSL *s) - goto f_err; - } - -- if (j != 0 && j == s->session->session_id_length -+ /* check if we want to resume the session based on external pre-shared secret */ -+ pre_shared = 0; -+ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb) -+ { -+ SSL_CIPHER *pref_cipher=NULL; -+ s->session->master_key_length=sizeof(s->session->master_key); -+ if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, -+ NULL, &pref_cipher, s->tls_session_secret_cb_arg)) -+ { -+ s->hit=1; -+ s->session->cipher=pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s,p+j); -+ s->session->session_id_length = j; -+ memcpy(s->session->session_id, p, j); -+ pre_shared = 1; -+ } -+ } -+ -+ if ((pre_shared || j != 0) && j == s->session->session_id_length - && memcmp(p,s->session->session_id,j) == 0) - { - if(s->sid_ctx_length != s->session->sid_ctx_length -diff -uprN openssl-0.9.8.orig/ssl/s3_srvr.c openssl-0.9.8/ssl/s3_srvr.c ---- openssl-0.9.8.orig/ssl/s3_srvr.c 2005-05-22 17:32:55.000000000 -0700 -+++ openssl-0.9.8/ssl/s3_srvr.c 2005-07-19 20:02:15.000000000 -0700 -@@ -955,6 +955,75 @@ int ssl3_get_client_hello(SSL *s) - } - #endif - -+ /* Check for TLS client hello extension here */ -+ if (p < (d+n) && s->version >= TLS1_VERSION) -+ { -+ if (s->tls_extension_cb) -+ { -+ TLS_EXTENSION tls_ext; -+ unsigned short ext_total_len; -+ -+ n2s(p, ext_total_len); -+ n2s(p, tls_ext.type); -+ n2s(p, tls_ext.length); -+ -+ // sanity check in TLS extension len -+ if (tls_ext.length > (d+n) - p) -+ { -+ // just cut the lenth to packet border -+ tls_ext.length = (d+n) - p; -+ } -+ -+ tls_ext.data = p; -+ -+ // returns an alert code or 0 -+ al = s->tls_extension_cb(s, &tls_ext, s->tls_extension_cb_arg); -+ if (al != 0) -+ { -+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_PEER_ERROR); -+ goto f_err; -+ } -+ } -+ } -+ -+ /* Check if we want to use external pre-shared secret for this handshake */ -+ /* for not reused session only */ -+ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb) -+ { -+ SSL_CIPHER *pref_cipher=NULL; -+ -+ s->session->master_key_length=sizeof(s->session->master_key); -+ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, -+ ciphers, &pref_cipher, s->tls_session_secret_cb_arg)) -+ { -+ s->hit=1; -+ s->session->ciphers=ciphers; -+ s->session->verify_result=X509_V_OK; -+ -+ ciphers=NULL; -+ -+ /* check if some cipher was preferred by call back */ -+ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s)); -+ if (pref_cipher == NULL) -+ { -+ al=SSL_AD_HANDSHAKE_FAILURE; -+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER); -+ goto f_err; -+ } -+ -+ s->session->cipher=pref_cipher; -+ -+ if (s->cipher_list) -+ sk_SSL_CIPHER_free(s->cipher_list); -+ -+ if (s->cipher_list_by_id) -+ sk_SSL_CIPHER_free(s->cipher_list_by_id); -+ -+ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers); -+ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers); -+ } -+ } -+ - /* Given s->session->ciphers and SSL_get_ciphers, we must - * pick a cipher */ - -diff -uprN openssl-0.9.8.orig/ssl/ssl_err.c openssl-0.9.8/ssl/ssl_err.c ---- openssl-0.9.8.orig/ssl/ssl_err.c 2005-06-10 12:51:16.000000000 -0700 -+++ openssl-0.9.8/ssl/ssl_err.c 2005-07-19 20:02:15.000000000 -0700 -@@ -242,6 +242,7 @@ static ERR_STRING_DATA SSL_str_functs[]= - {ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"}, - {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"}, - {ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"}, -+{ERR_FUNC(SSL_F_SSL_SET_HELLO_EXTENSION), "SSL_set_hello_extension"}, - {0,NULL} - }; - -diff -uprN openssl-0.9.8.orig/ssl/ssl.h openssl-0.9.8/ssl/ssl.h ---- openssl-0.9.8.orig/ssl/ssl.h 2005-06-10 12:51:16.000000000 -0700 -+++ openssl-0.9.8/ssl/ssl.h 2005-07-19 20:02:15.000000000 -0700 -@@ -340,6 +340,7 @@ extern "C" { - * 'struct ssl_st *' function parameters used to prototype callbacks - * in SSL_CTX. */ - typedef struct ssl_st *ssl_crock_st; -+typedef struct tls_extension_st TLS_EXTENSION; - - /* used to hold info on the particular ciphers used */ - typedef struct ssl_cipher_st -@@ -361,6 +362,8 @@ DECLARE_STACK_OF(SSL_CIPHER) - typedef struct ssl_st SSL; - typedef struct ssl_ctx_st SSL_CTX; - -+typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg); -+ - /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */ - typedef struct ssl_method_st - { -@@ -968,6 +971,15 @@ struct ssl_st - int first_packet; - int client_version; /* what was passed, used for - * SSLv3/TLS rollback check */ -+ -+ /* TLS externsions */ -+ TLS_EXTENSION *tls_extension; -+ int (*tls_extension_cb)(SSL *s, TLS_EXTENSION *tls_ext, void *arg); -+ void *tls_extension_cb_arg; -+ -+ /* TLS pre-shared secret session resumption */ -+ tls_session_secret_cb_fn tls_session_secret_cb; -+ void *tls_session_secret_cb_arg; - }; - - #ifdef __cplusplus -@@ -1533,6 +1545,13 @@ void *SSL_COMP_get_compression_methods(v - int SSL_COMP_add_compression_method(int id,void *cm); - #endif - -+/* TLS extensions functions */ -+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len); -+int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg); -+ -+/* Pre-shared secret session resumption functions */ -+int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg); -+ - /* BEGIN ERROR CODES */ - /* The following lines are auto generated by the script mkerr.pl. Any changes - * made after this point may be overwritten when the script is next run. -@@ -1714,6 +1733,7 @@ void ERR_load_SSL_strings(void); - #define SSL_F_TLS1_ENC 210 - #define SSL_F_TLS1_SETUP_KEY_BLOCK 211 - #define SSL_F_WRITE_PENDING 212 -+#define SSL_F_SSL_SET_HELLO_EXTENSION 213 - - /* Reason codes. */ - #define SSL_R_APP_DATA_IN_HANDSHAKE 100 -diff -uprN openssl-0.9.8.orig/ssl/ssl_sess.c openssl-0.9.8/ssl/ssl_sess.c ---- openssl-0.9.8.orig/ssl/ssl_sess.c 2005-04-29 13:10:06.000000000 -0700 -+++ openssl-0.9.8/ssl/ssl_sess.c 2005-07-19 20:02:15.000000000 -0700 -@@ -656,6 +656,15 @@ long SSL_CTX_get_timeout(const SSL_CTX * - return(s->session_timeout); - } - -+int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len, -+ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg) -+{ -+ if (s == NULL) return(0); -+ s->tls_session_secret_cb = tls_session_secret_cb; -+ s->tls_session_secret_cb_arg = arg; -+ return(1); -+} -+ - typedef struct timeout_param_st - { - SSL_CTX *ctx; -diff -uprN openssl-0.9.8.orig/ssl/t1_ext.c openssl-0.9.8/ssl/t1_ext.c ---- openssl-0.9.8.orig/ssl/t1_ext.c 1969-12-31 16:00:00.000000000 -0800 -+++ openssl-0.9.8/ssl/t1_ext.c 2005-07-19 20:03:29.000000000 -0700 -@@ -0,0 +1,48 @@ -+ -+#include <stdio.h> -+#include "ssl_locl.h" -+ -+ -+int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len) -+{ -+ if(s->version >= TLS1_VERSION) -+ { -+ if(s->tls_extension) -+ { -+ OPENSSL_free(s->tls_extension); -+ s->tls_extension = NULL; -+ } -+ -+ if(ext_data) -+ { -+ s->tls_extension = OPENSSL_malloc(sizeof(TLS_EXTENSION) + ext_len); -+ if(!s->tls_extension) -+ { -+ SSLerr(SSL_F_SSL_SET_HELLO_EXTENSION, ERR_R_MALLOC_FAILURE); -+ return 0; -+ } -+ -+ s->tls_extension->type = ext_type; -+ s->tls_extension->length = ext_len; -+ s->tls_extension->data = s->tls_extension + 1; -+ memcpy(s->tls_extension->data, ext_data, ext_len); -+ } -+ -+ return 1; -+ } -+ -+ return 0; -+} -+ -+int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg) -+{ -+ if(s->version >= TLS1_VERSION) -+ { -+ s->tls_extension_cb = cb; -+ s->tls_extension_cb_arg = arg; -+ -+ return 1; -+ } -+ -+ return 0; -+} -diff -uprN openssl-0.9.8.orig/ssl/t1_lib.c openssl-0.9.8/ssl/t1_lib.c ---- openssl-0.9.8.orig/ssl/t1_lib.c 2005-04-26 09:02:40.000000000 -0700 -+++ openssl-0.9.8/ssl/t1_lib.c 2005-07-19 20:02:15.000000000 -0700 -@@ -131,6 +131,10 @@ int tls1_new(SSL *s) - - void tls1_free(SSL *s) - { -+ if(s->tls_extension) -+ { -+ OPENSSL_free(s->tls_extension); -+ } - ssl3_free(s); - } - -diff -uprN openssl-0.9.8.orig/ssl/tls1.h openssl-0.9.8/ssl/tls1.h ---- openssl-0.9.8.orig/ssl/tls1.h 2003-07-22 05:34:21.000000000 -0700 -+++ openssl-0.9.8/ssl/tls1.h 2005-07-19 20:02:15.000000000 -0700 -@@ -282,6 +282,14 @@ extern "C" { - #define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/ - #endif - -+/* TLS extension struct */ -+struct tls_extension_st -+{ -+ unsigned short type; -+ unsigned short length; -+ void *data; -+}; -+ - #ifdef __cplusplus - } - #endif -diff -uprN openssl-0.9.8.orig/util/ssleay.num openssl-0.9.8/util/ssleay.num ---- openssl-0.9.8.orig/util/ssleay.num 2005-05-08 17:22:02.000000000 -0700 -+++ openssl-0.9.8/util/ssleay.num 2005-07-19 20:02:15.000000000 -0700 -@@ -226,3 +226,6 @@ DTLSv1_server_method - SSL_COMP_get_compression_methods 276 EXIST:!VMS:FUNCTION:COMP - SSL_COMP_get_compress_methods 276 EXIST:VMS:FUNCTION:COMP - SSL_SESSION_get_id 277 EXIST::FUNCTION: -+SSL_set_hello_extension 278 EXIST::FUNCTION: -+SSL_set_hello_extension_cb 279 EXIST::FUNCTION: -+SSL_set_session_secret_cb 280 EXIST::FUNCTION: diff --git a/contrib/wpa_supplicant/os.h b/contrib/wpa_supplicant/os.h deleted file mode 100644 index 25570a5e171a..000000000000 --- a/contrib/wpa_supplicant/os.h +++ /dev/null @@ -1,488 +0,0 @@ -/* - * wpa_supplicant/hostapd / OS specific functions - * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 */ - -#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_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_strdup -#ifdef _MSC_VER -#define os_strdup(s) _strdup(s) -#else -#define os_strdup(s) strdup(s) -#endif -#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 */ - - -#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/contrib/wpa_supplicant/os_internal.c b/contrib/wpa_supplicant/os_internal.c deleted file mode 100644 index b2183ea38f4d..000000000000 --- a/contrib/wpa_supplicant/os_internal.c +++ /dev/null @@ -1,441 +0,0 @@ -/* - * wpa_supplicant/hostapd / Internal implementation of OS specific functions - * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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; - } - - fread(buf, 1, *len, f); - 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; -} - - -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/contrib/wpa_supplicant/os_none.c b/contrib/wpa_supplicant/os_none.c deleted file mode 100644 index 7404e2293af5..000000000000 --- a/contrib/wpa_supplicant/os_none.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - * wpa_supplicant/hostapd / Empty OS specific functions - * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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; -} - - -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/contrib/wpa_supplicant/os_unix.c b/contrib/wpa_supplicant/os_unix.c deleted file mode 100644 index 7e3ab4adb4a5..000000000000 --- a/contrib/wpa_supplicant/os_unix.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - * wpa_supplicant/hostapd / OS specific functions for UNIX/POSIX systems - * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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" - -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; -} - - -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; - int last_errno; - - if (rel_path[0] == '/') - return strdup(rel_path); - - for (;;) { - buf = malloc(len); - if (buf == NULL) - return NULL; - cwd = getcwd(buf, len); - if (cwd == NULL) { - last_errno = errno; - free(buf); - if (last_errno != ERANGE) - return NULL; - len *= 2; - if (len > 2000) - return NULL; - } else { - buf[len - 1] = '\0'; - break; - } - } - - cwd_len = strlen(cwd); - rel_len = strlen(rel_path); - ret_len = cwd_len + 1 + rel_len + 1; - ret = malloc(ret_len); - if (ret) { - memcpy(ret, cwd, cwd_len); - ret[cwd_len] = '/'; - memcpy(ret + cwd_len + 1, rel_path, rel_len); - ret[ret_len - 1] = '\0'; - } - 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 = malloc(*len); - if (buf == NULL) { - fclose(f); - return NULL; - } - - if (fread(buf, 1, *len, f) != *len) { - fclose(f); - free(buf); - return NULL; - } - - fclose(f); - - return buf; -} - - -void * os_zalloc(size_t size) -{ - return calloc(1, size); -} diff --git a/contrib/wpa_supplicant/pcsc_funcs.c b/contrib/wpa_supplicant/pcsc_funcs.c deleted file mode 100644 index cf8e3b009506..000000000000 --- a/contrib/wpa_supplicant/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 <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 <winscard.h> - -#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 <file_id, 2 bytes> - * GET RESPONSE: C0 00 00 <len> - * RUN GSM ALG: 88 00 00 00 <RAND len = 10> - * RUN UMTS ALG: 88 00 81 <len=0x22> data: 0x10 | RAND | 0x10 | AUTN - * P1 = ID of alg in card - * P2 = ID of secret key - * READ BINARY: B0 <offset high> <offset low> <len> - * READ RECORD: B2 <record number> <mode> <len> - * P2 (mode) = '02' (next record), '03' (previous record), - * '04' (absolute mode) - * VERIFY CHV: 20 00 <CHV number> 08 - * CHANGE CHV: 24 00 <CHV number> 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/contrib/wpa_supplicant/pcsc_funcs.h b/contrib/wpa_supplicant/pcsc_funcs.h deleted file mode 100644 index 543f7c598419..000000000000 --- a/contrib/wpa_supplicant/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 <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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/contrib/wpa_supplicant/pmksa_cache.c b/contrib/wpa_supplicant/pmksa_cache.c deleted file mode 100644 index 127c3571bb6a..000000000000 --- a/contrib/wpa_supplicant/pmksa_cache.c +++ /dev/null @@ -1,502 +0,0 @@ -/* - * WPA Supplicant - RSN PMKSA cache - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "config_ssid.h" -#include "sha1.h" -#include "wpa_i.h" -#include "l2_packet.h" -#include "eapol_sm.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; -}; - - -/** - * rsn_pmkid - Calculate PMK identifier - * @pmk: Pairwise master key - * @pmk_len: Length of pmk in bytes - * @aa: Authenticator address - * @spa: Supplicant address - * - * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy - * PMKID = HMAC-SHA1-128(PMK, "PMK Name" || AA || SPA) - */ -static void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, - const u8 *spa, u8 *pmkid) -{ - char *title = "PMK Name"; - const u8 *addr[3]; - const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN }; - unsigned char hash[SHA1_MAC_LEN]; - - addr[0] = (u8 *) title; - addr[1] = aa; - addr[2] = spa; - - hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash); - os_memcpy(pmkid, hash, PMKID_LEN); -} - - -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 - * @ssid: The network configuration for which this PMK is being added - * 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, struct wpa_ssid *ssid) -{ - struct rsn_pmksa_cache_entry *entry, *pos, *prev; - struct os_time now; - - if (pmksa->sm->proto != WPA_PROTO_RSN || 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); - 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 = WPA_KEY_MGMT_IEEE8021X; - os_memcpy(entry->aa, aa, ETH_ALEN); - entry->ssid = ssid; - - /* 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->ssid = 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->ssid); - 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() - * @ssid: Pointer to the current network configuration - * @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, - struct wpa_ssid *ssid, const u8 *aa) -{ - struct rsn_pmksa_cache_entry *entry = pmksa->pmksa; - - if (ssid == NULL) - return NULL; - while (entry) { - if (entry->ssid == ssid) { - 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 - * @ssid: The network configuration for the current network - * @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, struct wpa_ssid *ssid, - 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, ssid, - 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 - * @sm: Pointer to WPA state machine data from wpa_sm_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 wpa_sm *sm, 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 = sm->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/contrib/wpa_supplicant/pmksa_cache.h b/contrib/wpa_supplicant/pmksa_cache.h deleted file mode 100644 index 7fe6ff3429f3..000000000000 --- a/contrib/wpa_supplicant/pmksa_cache.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * wpa_supplicant - WPA2/RSN PMKSA cache functions - * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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; - struct wpa_ssid *ssid; - 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 wpa_sm *sm, 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, struct wpa_ssid *ssid); -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, struct wpa_ssid *ssid, - int try_opportunistic); -struct rsn_pmksa_cache_entry * -pmksa_cache_get_opportunistic(struct rsn_pmksa_cache *pmksa, - struct wpa_ssid *ssid, 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 wpa_sm *sm, 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, struct wpa_ssid *ssid) -{ - 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, - struct wpa_ssid *ssid, - int try_opportunistic) -{ - return -1; -} - -#endif /* IEEE8021X_EAPOL and !CONFIG_NO_WPA2 */ - -#endif /* PMKSA_CACHE_H */ diff --git a/contrib/wpa_supplicant/preauth.c b/contrib/wpa_supplicant/preauth.c deleted file mode 100644 index 4873c49030e2..000000000000 --- a/contrib/wpa_supplicant/preauth.c +++ /dev/null @@ -1,524 +0,0 @@ -/* - * WPA Supplicant - RSN pre-authentication - * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "driver.h" -#include "eloop.h" -#include "config.h" -#include "l2_packet.h" -#include "eapol_sm.h" -#include "preauth.h" -#include "pmksa_cache.h" -#include "wpa_i.h" - - -#define PMKID_CANDIDATE_PRIO_SCAN 1000 - - -struct rsn_pmksa_candidate { - struct rsn_pmksa_candidate *next; - 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, *prev; - - if (sm == NULL) - return; - - entry = sm->pmksa_candidates; - sm->pmksa_candidates = NULL; - while (entry) { - prev = entry; - entry = entry->next; - os_free(prev); - } -} - - -#if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA2) - -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 || - os_memcmp(sm->preauth_bssid, "\x00\x00\x00\x00\x00\x00", - ETH_ALEN) == 0 || - 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->cur_ssid); - } else { - wpa_msg(sm->ctx->ctx, MSG_INFO, "RSN: failed to get " - "master session key from pre-auth EAPOL state " - "machines"); - success = 0; - } - } - - wpa_msg(sm->ctx->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->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 - * @config: Current network 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 wpa_ssid *config) -{ - struct eapol_config eapol_conf; - struct eapol_ctx *ctx; - - if (sm->preauth_eapol) - return -1; - - wpa_msg(sm->ctx->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; - if (config) - eapol_conf.workaround = config->eap_workaround; - eapol_sm_notify_config(sm->preauth_eapol, config, &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; - - if (sm->pmksa_candidates == NULL) - return; - - /* TODO: drop priority for old candidate entries */ - - wpa_msg(sm->ctx->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) { - wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: not in suitable state " - "for new pre-authentication"); - return; /* invalid state for new pre-auth */ - } - - while (sm->pmksa_candidates) { - struct rsn_pmksa_cache_entry *p = NULL; - candidate = sm->pmksa_candidates; - 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->ctx, MSG_DEBUG, "RSN: PMKSA " - "candidate " MACSTR - " selected for pre-authentication", - MAC2STR(candidate->bssid)); - sm->pmksa_candidates = candidate->next; - rsn_preauth_init(sm, candidate->bssid, sm->cur_ssid); - os_free(candidate); - return; - } - wpa_msg(sm->ctx->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); - } - - sm->pmksa_candidates = candidate->next; - os_free(candidate); - } - wpa_msg(sm->ctx->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, *prev, *pos; - - if (sm->cur_ssid && sm->cur_ssid->proactive_key_caching) - pmksa_cache_get_opportunistic(sm->pmksa, sm->cur_ssid, 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. */ - prev = NULL; - cand = sm->pmksa_candidates; - while (cand) { - if (os_memcmp(cand->bssid, bssid, ETH_ALEN) == 0) { - if (prev) - prev->next = cand->next; - else - sm->pmksa_candidates = cand->next; - break; - } - prev = cand; - cand = cand->next; - } - - if (cand) { - 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. */ - prev = NULL; - pos = sm->pmksa_candidates; - while (pos) { - if (cand->priority <= pos->priority) - break; - prev = pos; - pos = pos->next; - } - cand->next = pos; - if (prev) - prev->next = cand; - else - sm->pmksa_candidates = cand; - - wpa_msg(sm->ctx->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 - Process scan results to find PMKSA candidates - * @sm: Pointer to WPA state machine data from wpa_sm_init() - * @results: Scan results - * @count: Number of BSSes in scan results - * - * This functions goes through the scan results and adds all suitable APs - * (Authenticators) into PMKSA candidate list. - */ -void rsn_preauth_scan_results(struct wpa_sm *sm, - struct wpa_scan_result *results, int count) -{ - struct wpa_scan_result *r; - struct wpa_ie_data ie; - int i; - struct rsn_pmksa_cache_entry *pmksa; - - if (sm->cur_ssid == NULL) - return; - - /* - * TODO: is it ok to free all candidates? What about the entries - * received from EVENT_PMKID_CANDIDATE? - */ - pmksa_candidate_free(sm); - - for (i = count - 1; i >= 0; i--) { - r = &results[i]; - if (r->ssid_len != sm->cur_ssid->ssid_len || - os_memcmp(r->ssid, sm->cur_ssid->ssid, - r->ssid_len) != 0) - continue; - - if (os_memcmp(r->bssid, sm->bssid, ETH_ALEN) == 0) - continue; - - if (r->rsn_ie_len == 0 || - wpa_parse_wpa_ie(r->rsn_ie, r->rsn_ie_len, &ie)) - continue; - - pmksa = pmksa_cache_get(sm->pmksa, r->bssid, NULL); - if (pmksa && - (!pmksa->opportunistic || - !(ie.capabilities & WPA_CAPABILITY_PREAUTH))) - continue; - - /* - * Give less priority to candidates found from normal - * scan results. - */ - pmksa_candidate_add(sm, r->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/contrib/wpa_supplicant/preauth.h b/contrib/wpa_supplicant/preauth.h deleted file mode 100644 index 07e3e006622a..000000000000 --- a/contrib/wpa_supplicant/preauth.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * wpa_supplicant - WPA2/RSN pre-authentication functions - * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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_result; - -#ifndef CONFIG_NO_WPA - -void pmksa_candidate_free(struct wpa_sm *sm); - -#else /* CONFIG_NO_WPA */ - -static inline void pmksa_candidate_free(struct wpa_sm *sm) -{ -} - -#endif /* CONFIG_NO_WPA */ - - -#if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA2) - -int rsn_preauth_init(struct wpa_sm *sm, const u8 *dst, - struct wpa_ssid *config); -void rsn_preauth_deinit(struct wpa_sm *sm); -void rsn_preauth_scan_results(struct wpa_sm *sm, - struct wpa_scan_result *results, int count); -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 rsn_preauth_candidate_process(struct wpa_sm *sm) -{ -} - -static inline int rsn_preauth_init(struct wpa_sm *sm, const u8 *dst, - struct wpa_ssid *config) -{ - return -1; -} - -static inline void rsn_preauth_deinit(struct wpa_sm *sm) -{ -} -static inline void rsn_preauth_scan_results(struct wpa_sm *sm, - struct wpa_scan_result *results, - int count) -{ -} - -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/contrib/wpa_supplicant/preauth_test.c b/contrib/wpa_supplicant/preauth_test.c deleted file mode 100644 index 6758d9e90c2f..000000000000 --- a/contrib/wpa_supplicant/preauth_test.c +++ /dev/null @@ -1,383 +0,0 @@ -/* - * WPA Supplicant - test code for pre-authentication - * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * IEEE 802.1X Supplicant test code (to be used in place of wpa_supplicant.c. - * Not used in production version. - */ - -#include "includes.h" -#include <assert.h> - -#include "common.h" -#include "config.h" -#include "eapol_sm.h" -#include "eloop.h" -#include "wpa.h" -#include "eap.h" -#include "wpa_supplicant.h" -#include "wpa_supplicant_i.h" -#include "l2_packet.h" -#include "ctrl_iface.h" -#include "pcsc_funcs.h" -#include "preauth.h" -#include "pmksa_cache.h" - - -extern int wpa_debug_level; -extern int wpa_debug_show_keys; - -struct wpa_driver_ops *wpa_supplicant_drivers[] = { NULL }; - - -struct preauth_test_data { - int auth_timed_out; -}; - - -static void _wpa_supplicant_disassociate(void *wpa_s, int reason_code) -{ - wpa_supplicant_disassociate(wpa_s, reason_code); -} - - -static void _wpa_supplicant_deauthenticate(void *wpa_s, int reason_code) -{ - wpa_supplicant_deauthenticate(wpa_s, reason_code); -} - - -static u8 * wpa_alloc_eapol(const struct wpa_supplicant *wpa_s, u8 type, - const void *data, u16 data_len, - size_t *msg_len, void **data_pos) -{ - struct ieee802_1x_hdr *hdr; - - *msg_len = sizeof(*hdr) + data_len; - hdr = os_malloc(*msg_len); - if (hdr == NULL) - return NULL; - - hdr->version = wpa_s->conf->eapol_version; - hdr->type = type; - hdr->length = htons(data_len); - - if (data) - os_memcpy(hdr + 1, data, data_len); - else - os_memset(hdr + 1, 0, data_len); - - if (data_pos) - *data_pos = hdr + 1; - - return (u8 *) hdr; -} - - -static u8 * _wpa_alloc_eapol(void *wpa_s, u8 type, - const void *data, u16 data_len, - size_t *msg_len, void **data_pos) -{ - return wpa_alloc_eapol(wpa_s, type, data, data_len, msg_len, data_pos); -} - - -static void _wpa_supplicant_set_state(void *ctx, wpa_states state) -{ - struct wpa_supplicant *wpa_s = ctx; - wpa_s->wpa_state = state; -} - - -static wpa_states _wpa_supplicant_get_state(void *ctx) -{ - struct wpa_supplicant *wpa_s = ctx; - return wpa_s->wpa_state; -} - - -static int wpa_ether_send(void *wpa_s, const u8 *dest, u16 proto, - const u8 *buf, size_t len) -{ - printf("%s - not implemented\n", __func__); - return -1; -} - - -static struct wpa_ssid * _wpa_supplicant_get_ssid(void *wpa_s) -{ - return wpa_supplicant_get_ssid(wpa_s); -} - - -static void _wpa_supplicant_cancel_auth_timeout(void *wpa_s) -{ - wpa_supplicant_cancel_auth_timeout(wpa_s); -} - - -static int wpa_supplicant_get_beacon_ie(void *wpa_s) -{ - printf("%s - not implemented\n", __func__); - return -1; -} - - -void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) -{ - printf("%s - not implemented\n", __func__); -} - - -static int wpa_supplicant_get_bssid(void *wpa_s, u8 *bssid) -{ - printf("%s - not implemented\n", __func__); - return -1; -} - - -static int wpa_supplicant_set_key(void *wpa_s, 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) -{ - printf("%s - not implemented\n", __func__); - return -1; -} - - -static int wpa_supplicant_mlme_setprotection(void *wpa_s, const u8 *addr, - int protection_type, - int key_type) -{ - printf("%s - not implemented\n", __func__); - return -1; -} - - -static int wpa_supplicant_add_pmkid(void *wpa_s, - const u8 *bssid, const u8 *pmkid) -{ - printf("%s - not implemented\n", __func__); - return -1; -} - - -static int wpa_supplicant_remove_pmkid(void *wpa_s, - const u8 *bssid, const u8 *pmkid) -{ - printf("%s - not implemented\n", __func__); - return -1; -} - - -static void wpa_supplicant_set_config_blob(void *ctx, - struct wpa_config_blob *blob) -{ - struct wpa_supplicant *wpa_s = ctx; - wpa_config_set_blob(wpa_s->conf, blob); -} - - -static const struct wpa_config_blob * -wpa_supplicant_get_config_blob(void *ctx, const char *name) -{ - struct wpa_supplicant *wpa_s = ctx; - return wpa_config_get_blob(wpa_s->conf, name); -} - - -static void test_eapol_clean(struct wpa_supplicant *wpa_s) -{ - rsn_preauth_deinit(wpa_s->wpa); - pmksa_candidate_free(wpa_s->wpa); - wpa_sm_deinit(wpa_s->wpa); - scard_deinit(wpa_s->scard); - if (wpa_s->ctrl_iface) { - wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface); - wpa_s->ctrl_iface = NULL; - } - wpa_config_free(wpa_s->conf); -} - - -static void eapol_test_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct preauth_test_data *p = eloop_ctx; - printf("EAPOL test timed out\n"); - p->auth_timed_out = 1; - eloop_terminate(); -} - - -static void eapol_test_poll(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_supplicant *wpa_s = eloop_ctx; - if (!rsn_preauth_in_progress(wpa_s->wpa)) - eloop_terminate(); - else { - eloop_register_timeout(0, 100000, eapol_test_poll, eloop_ctx, - timeout_ctx); - } -} - - -static struct wpa_driver_ops dummy_driver; - - -static void wpa_init_conf(struct wpa_supplicant *wpa_s, const char *ifname) -{ - struct l2_packet_data *l2; - struct wpa_sm_ctx *ctx; - - os_memset(&dummy_driver, 0, sizeof(dummy_driver)); - wpa_s->driver = &dummy_driver; - - ctx = os_zalloc(sizeof(*ctx)); - assert(ctx != NULL); - - ctx->ctx = wpa_s; - ctx->set_state = _wpa_supplicant_set_state; - ctx->get_state = _wpa_supplicant_get_state; - ctx->deauthenticate = _wpa_supplicant_deauthenticate; - ctx->disassociate = _wpa_supplicant_disassociate; - ctx->set_key = wpa_supplicant_set_key; - ctx->scan = wpa_supplicant_scan; - ctx->get_ssid = _wpa_supplicant_get_ssid; - ctx->get_bssid = wpa_supplicant_get_bssid; - ctx->ether_send = wpa_ether_send; - ctx->get_beacon_ie = wpa_supplicant_get_beacon_ie; - ctx->alloc_eapol = _wpa_alloc_eapol; - ctx->cancel_auth_timeout = _wpa_supplicant_cancel_auth_timeout; - ctx->add_pmkid = wpa_supplicant_add_pmkid; - ctx->remove_pmkid = wpa_supplicant_remove_pmkid; - ctx->set_config_blob = wpa_supplicant_set_config_blob; - ctx->get_config_blob = wpa_supplicant_get_config_blob; - ctx->mlme_setprotection = wpa_supplicant_mlme_setprotection; - - wpa_s->wpa = wpa_sm_init(ctx); - assert(wpa_s->wpa != NULL); - wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, WPA_PROTO_RSN); - - os_strncpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname)); - wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname, NULL); - - l2 = l2_packet_init(wpa_s->ifname, NULL, ETH_P_RSN_PREAUTH, NULL, - NULL, 0); - assert(l2 != NULL); - if (l2_packet_get_own_addr(l2, wpa_s->own_addr)) { - wpa_printf(MSG_WARNING, "Failed to get own L2 address\n"); - exit(-1); - } - l2_packet_deinit(l2); - wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr); -} - - -static void eapol_test_terminate(int sig, void *eloop_ctx, - void *signal_ctx) -{ - struct wpa_supplicant *wpa_s = eloop_ctx; - wpa_msg(wpa_s, MSG_INFO, "Signal %d received - terminating", sig); - eloop_terminate(); -} - - -int main(int argc, char *argv[]) -{ - struct wpa_supplicant wpa_s; - int ret = 1; - u8 bssid[ETH_ALEN]; - struct preauth_test_data preauth_test; - - if (os_program_init()) - return -1; - - os_memset(&preauth_test, 0, sizeof(preauth_test)); - - wpa_debug_level = 0; - wpa_debug_show_keys = 1; - - if (argc != 4) { - printf("usage: preauth_test <conf> <target MAC address> " - "<ifname>\n"); - return -1; - } - - if (hwaddr_aton(argv[2], bssid)) { - printf("Failed to parse target address '%s'.\n", argv[2]); - return -1; - } - - if (eap_peer_register_methods()) { - wpa_printf(MSG_ERROR, "Failed to register EAP methods"); - return -1; - } - - if (eloop_init(&wpa_s)) { - wpa_printf(MSG_ERROR, "Failed to initialize event loop"); - return -1; - } - - os_memset(&wpa_s, 0, sizeof(wpa_s)); - wpa_s.conf = wpa_config_read(argv[1]); - if (wpa_s.conf == NULL) { - printf("Failed to parse configuration file '%s'.\n", argv[1]); - return -1; - } - if (wpa_s.conf->ssid == NULL) { - printf("No networks defined.\n"); - return -1; - } - - wpa_init_conf(&wpa_s, argv[3]); - wpa_s.ctrl_iface = wpa_supplicant_ctrl_iface_init(&wpa_s); - if (wpa_s.ctrl_iface == NULL) { - printf("Failed to initialize control interface '%s'.\n" - "You may have another preauth_test process already " - "running or the file was\n" - "left by an unclean termination of preauth_test in " - "which case you will need\n" - "to manually remove this file before starting " - "preauth_test again.\n", - wpa_s.conf->ctrl_interface); - return -1; - } - if (wpa_supplicant_scard_init(&wpa_s, wpa_s.conf->ssid)) - return -1; - - if (rsn_preauth_init(wpa_s.wpa, bssid, wpa_s.conf->ssid)) - return -1; - - eloop_register_timeout(30, 0, eapol_test_timeout, &preauth_test, NULL); - eloop_register_timeout(0, 100000, eapol_test_poll, &wpa_s, NULL); - eloop_register_signal_terminate(eapol_test_terminate, NULL); - eloop_register_signal_reconfig(eapol_test_terminate, NULL); - eloop_run(); - - if (preauth_test.auth_timed_out) - ret = -2; - else { - ret = pmksa_cache_set_current(wpa_s.wpa, NULL, bssid, NULL, 0) - ? 0 : -3; - } - - test_eapol_clean(&wpa_s); - - eap_peer_unregister_methods(); - - eloop_destroy(); - - os_program_deinit(); - - return ret; -} diff --git a/contrib/wpa_supplicant/radius.c b/contrib/wpa_supplicant/radius.c deleted file mode 100644 index afa4f933ee98..000000000000 --- a/contrib/wpa_supplicant/radius.c +++ /dev/null @@ -1,1229 +0,0 @@ -/* - * hostapd / RADIUS message processing - * Copyright (c) 2002-2008, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "md5.h" -#include "crypto.h" - - -struct radius_msg *radius_msg_new(u8 code, u8 identifier) -{ - struct radius_msg *msg; - - msg = os_malloc(sizeof(*msg)); - if (msg == NULL) - return NULL; - - if (radius_msg_initialize(msg, RADIUS_DEFAULT_MSG_SIZE)) { - os_free(msg); - return NULL; - } - - radius_msg_set_hdr(msg, code, identifier); - - return msg; -} - - -int radius_msg_initialize(struct radius_msg *msg, size_t init_len) -{ - if (msg == NULL || init_len < sizeof(struct radius_hdr)) - return -1; - - os_memset(msg, 0, sizeof(*msg)); - msg->buf = wpa_zalloc(init_len); - if (msg->buf == NULL) - return -1; - - msg->buf_size = init_len; - msg->hdr = (struct radius_hdr *) msg->buf; - msg->buf_used = sizeof(*msg->hdr); - - msg->attrs = - os_malloc(RADIUS_DEFAULT_ATTR_COUNT * sizeof(*msg->attrs)); - if (msg->attrs == NULL) { - os_free(msg->buf); - msg->buf = NULL; - msg->hdr = NULL; - return -1; - } - - msg->attr_size = RADIUS_DEFAULT_ATTR_COUNT; - msg->attr_used = 0; - - return 0; -} - - -void radius_msg_set_hdr(struct radius_msg *msg, u8 code, u8 identifier) -{ - msg->hdr->code = code; - msg->hdr->identifier = identifier; -} - - -void radius_msg_free(struct radius_msg *msg) -{ - if (msg->buf != NULL) { - os_free(msg->buf); - msg->buf = NULL; - msg->hdr = NULL; - } - msg->buf_size = msg->buf_used = 0; - - if (msg->attrs != NULL) { - os_free(msg->attrs); - msg->attrs = NULL; - } - msg->attr_size = msg->attr_used = 0; -} - - -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_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_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++) { - radius_msg_dump_attr(msg->attrs[i]); - } -} - - -int radius_msg_finish(struct radius_msg *msg, 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) { - printf("WARNING: Could not add " - "Message-Authenticator\n"); - return -1; - } - msg->hdr->length = htons(msg->buf_used); - hmac_md5(secret, secret_len, msg->buf, msg->buf_used, - (u8 *) (attr + 1)); - } else - msg->hdr->length = htons(msg->buf_used); - - if (msg->buf_used > 0xffff) { - printf("WARNING: too long RADIUS message (%lu)\n", - (unsigned long) msg->buf_used); - 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(msg->buf_used); - os_memcpy(msg->hdr->authenticator, req_authenticator, - sizeof(msg->hdr->authenticator)); - hmac_md5(secret, secret_len, msg->buf, msg->buf_used, - (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] = (u8 *) (msg->hdr + 1); - len[2] = msg->buf_used - sizeof(*msg->hdr); - addr[3] = secret; - len[3] = secret_len; - md5_vector(4, addr, len, msg->hdr->authenticator); - - if (msg->buf_used > 0xffff) { - printf("WARNING: too long RADIUS message (%lu)\n", - (unsigned long) msg->buf_used); - return -1; - } - return 0; -} - - -void radius_msg_finish_acct(struct radius_msg *msg, u8 *secret, - size_t secret_len) -{ - const u8 *addr[2]; - size_t len[2]; - - msg->hdr->length = htons(msg->buf_used); - os_memset(msg->hdr->authenticator, 0, MD5_MAC_LEN); - addr[0] = msg->buf; - len[0] = msg->buf_used; - addr[1] = secret; - len[1] = secret_len; - md5_vector(2, addr, len, msg->hdr->authenticator); - - if (msg->buf_used > 0xffff) { - printf("WARNING: too long RADIUS messages (%lu)\n", - (unsigned long) msg->buf_used); - } -} - - -static int radius_msg_add_attr_to_array(struct radius_msg *msg, - struct radius_attr_hdr *attr) -{ - if (msg->attr_used >= msg->attr_size) { - struct radius_attr_hdr **nattrs; - int nlen = msg->attr_size * 2; - - nattrs = os_realloc(msg->attrs, nlen * sizeof(*msg->attrs)); - if (nattrs == NULL) - return -1; - - msg->attrs = nattrs; - msg->attr_size = nlen; - } - - msg->attrs[msg->attr_used++] = attr; - - 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 = msg->buf_used + sizeof(*attr) + data_len; - - if (msg->buf_size < buf_needed) { - /* allocate more space for message buffer */ - unsigned char *nbuf; - size_t i, nlen = msg->buf_size; - int diff; - - while (nlen < buf_needed) - nlen *= 2; - nbuf = os_realloc(msg->buf, nlen); - if (nbuf == NULL) - return NULL; - diff = nbuf - msg->buf; - msg->buf = nbuf; - msg->hdr = (struct radius_hdr *) msg->buf; - /* adjust attr pointers to match with the new buffer */ - for (i = 0; i < msg->attr_used; i++) - msg->attrs[i] = (struct radius_attr_hdr *) - (((u8 *) msg->attrs[i]) + diff); - os_memset(msg->buf + msg->buf_size, 0, nlen - msg->buf_size); - msg->buf_size = nlen; - } - - attr = (struct radius_attr_hdr *) (msg->buf + msg->buf_used); - attr->type = type; - attr->length = sizeof(*attr) + data_len; - if (data_len > 0) - os_memcpy(attr + 1, data, data_len); - - msg->buf_used += sizeof(*attr) + data_len; - - if (radius_msg_add_attr_to_array(msg, attr)) - return NULL; - - return attr; -} - - -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) { - printf("Invalid RADIUS message length\n"); - return NULL; - } - - if (msg_len < len) { - printf("Ignored %lu extra bytes after RADIUS message\n", - (unsigned long) len - msg_len); - } - - msg = os_malloc(sizeof(*msg)); - if (msg == NULL) - return NULL; - - if (radius_msg_initialize(msg, msg_len)) { - os_free(msg); - return NULL; - } - - os_memcpy(msg->buf, data, msg_len); - msg->buf_size = msg->buf_used = msg_len; - - /* parse attributes */ - pos = (unsigned char *) (msg->hdr + 1); - end = msg->buf + msg->buf_used; - 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); - os_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; - - if (msg == NULL) - return NULL; - - len = 0; - for (i = 0; i < msg->attr_used; i++) { - if (msg->attrs[i]->type == RADIUS_ATTR_EAP_MESSAGE) - len += msg->attrs[i]->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++) { - if (msg->attrs[i]->type == RADIUS_ATTR_EAP_MESSAGE) { - struct radius_attr_hdr *attr = msg->attrs[i]; - 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; - size_t i; - - for (i = 0; i < msg->attr_used; i++) { - if (msg->attrs[i]->type == RADIUS_ATTR_MESSAGE_AUTHENTICATOR) { - if (attr != NULL) { - printf("Multiple Message-Authenticator " - "attributes in RADIUS message\n"); - return 1; - } - attr = msg->attrs[i]; - } - } - - 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, msg->buf, msg->buf_used, 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] = (u8 *) (msg->hdr + 1); - len[2] = msg->buf_used - sizeof(*msg->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 = src->attrs[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 = msg->attrs[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]; - - saltbuf[0] = salt >> 8; - saltbuf[1] = 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, - 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 = wpa_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, - 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 = wpa_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; - *pos++ = salt >> 8; - *pos++ = salt; - 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; - *pos++ = salt >> 8; - *pos++ = salt; - 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, - u8 *data, size_t data_len, - 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; - size_t i, dlen; - - for (i = 0; i < msg->attr_used; i++) { - if (msg->attrs[i]->type == type) { - attr = msg->attrs[i]; - 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; - - for (i = 0; i < msg->attr_used; i++) { - if (msg->attrs[i]->type == type && - (start == NULL || (u8 *) msg->attrs[i] > start)) { - attr = msg->attrs[i]; - 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++) { - if (msg->attrs[i]->type == type && - msg->attrs[i]->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 = msg->attrs[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 = (data[1] << 16) | (data[2] << 8) | data[3]; - break; - case RADIUS_ATTR_TUNNEL_MEDIUM_TYPE: - if (attr->length != 6) - break; - tun->tag_used++; - tun->medium_type = - (data[1] << 16) | (data[2] << 8) | data[3]; - 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; -} diff --git a/contrib/wpa_supplicant/radius.h b/contrib/wpa_supplicant/radius.h deleted file mode 100644 index d4375376a94f..000000000000 --- a/contrib/wpa_supplicant/radius.h +++ /dev/null @@ -1,267 +0,0 @@ -/* - * hostapd / RADIUS message processing - * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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_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_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; -}; - - -/* RADIUS message structure for new and parsed messages */ -struct radius_msg { - unsigned char *buf; - size_t buf_size; /* total size allocated for buf */ - size_t buf_used; /* bytes used in buf */ - - struct radius_hdr *hdr; - - struct radius_attr_hdr **attrs; /* array of pointers to attributes */ - size_t attr_size; /* total size of the attribute pointer array */ - size_t attr_used; /* total number of attributes in the array */ -}; - - -/* 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_msg *radius_msg_new(u8 code, u8 identifier); -int radius_msg_initialize(struct radius_msg *msg, size_t init_len); -void radius_msg_set_hdr(struct radius_msg *msg, 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, 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, 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, - 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, - 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, - u8 *data, size_t data_len, - 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); - -#endif /* RADIUS_H */ diff --git a/contrib/wpa_supplicant/radius_client.c b/contrib/wpa_supplicant/radius_client.c deleted file mode 100644 index 81cd9c58b16b..000000000000 --- a/contrib/wpa_supplicant/radius_client.c +++ /dev/null @@ -1,1219 +0,0 @@ -/* - * hostapd / RADIUS client - * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "hostapd.h" -#include "radius.h" -#include "radius_client.h" -#include "eloop.h" - -/* Defaults for RADIUS retransmit values (exponential backoff) */ -#define RADIUS_CLIENT_FIRST_WAIT 3 /* seconds */ -#define RADIUS_CLIENT_MAX_WAIT 120 /* seconds */ -#define RADIUS_CLIENT_MAX_RETRIES 10 /* maximum number of retransmit attempts - * before entry is removed from retransmit - * list */ -#define RADIUS_CLIENT_MAX_ENTRIES 30 /* maximum number of entries in retransmit - * list (oldest will be removed, if this - * limit is exceeded) */ -#define RADIUS_CLIENT_NUM_FAILOVER 4 /* try to change RADIUS server after this - * many failed retry attempts */ - - -struct radius_rx_handler { - RadiusRxResult (*handler)(struct radius_msg *msg, - struct radius_msg *req, - u8 *shared_secret, size_t shared_secret_len, - void *data); - void *data; -}; - - -/* RADIUS message retransmit list */ -struct radius_msg_list { - u8 addr[ETH_ALEN]; /* STA/client address; used to find RADIUS messages - * for the same STA. */ - struct radius_msg *msg; - RadiusType msg_type; - os_time_t first_try; - os_time_t next_try; - int attempts; - int next_wait; - struct os_time last_attempt; - - u8 *shared_secret; - size_t shared_secret_len; - - /* TODO: server config with failover to backup server(s) */ - - struct radius_msg_list *next; -}; - - -struct radius_client_data { - void *ctx; - struct hostapd_radius_servers *conf; - - int auth_serv_sock; /* socket for authentication RADIUS messages */ - int acct_serv_sock; /* socket for accounting RADIUS messages */ - int auth_serv_sock6; - int acct_serv_sock6; - int auth_sock; /* currently used socket */ - int acct_sock; /* currently used socket */ - - struct radius_rx_handler *auth_handlers; - size_t num_auth_handlers; - struct radius_rx_handler *acct_handlers; - size_t num_acct_handlers; - - struct radius_msg_list *msgs; - size_t num_msgs; - - 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->msg); - os_free(req); -} - - -int radius_client_register(struct radius_client_data *radius, - RadiusType msg_type, - RadiusRxResult (*handler)(struct radius_msg *msg, - struct radius_msg *req, - 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; - - 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)", - entry->msg->hdr->identifier); - - os_get_time(&entry->last_attempt); - if (send(s, entry->msg->buf, entry->msg->buf_used, 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, 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); - os_free(msg); - return; - } - - entry = wpa_zalloc(sizeof(*entry)); - if (entry == NULL) { - printf("Failed to add RADIUS packet into retransmit list\n"); - radius_msg_free(msg); - os_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; - } -} - - -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; - u8 *shared_secret; - size_t shared_secret_len; - char *name; - int s, res; - - 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); - - res = send(s, msg->buf, msg->buf_used, 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_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; - } - - hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_DEBUG, "Received RADIUS message"); - if (conf->msg_dumps) - radius_msg_dump(msg); - - switch (msg->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)) && - req->msg->hdr->identifier == msg->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, msg->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); - os_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, msg->hdr->code, msg->hdr->identifier, - invalid_authenticator ? " [INVALID AUTHENTICATOR]" : - ""); - radius_client_msg_free(req); - - fail: - radius_msg_free(msg); - os_free(msg); -} - - -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 (entry->msg->hdr->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; -} - - -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); -} - - -void radius_client_update_acct_msgs(struct radius_client_data *radius, - 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; -#ifdef CONFIG_IPV6 - struct sockaddr_in6 serv6; -#endif /* CONFIG_IPV6 */ - struct sockaddr *addr; - socklen_t addrlen; - char abuf[50]; - int sel_sock; - struct radius_msg_list *entry; - - 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 (connect(sel_sock, addr, addrlen) < 0) { - perror("connect[radius]"); - return -1; - } - - 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_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 - 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 - 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; -} - - -struct radius_client_data * -radius_client_init(void *ctx, struct hostapd_radius_servers *conf) -{ - struct radius_client_data *radius; - - radius = wpa_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; -} - - -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); - - 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); -} - - -void radius_client_flush_auth(struct radius_client_data *radius, 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); -} - - -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; -} - - -static int radius_servers_diff(struct hostapd_radius_server *nserv, - struct hostapd_radius_server *oserv, - int num) -{ - int i; - - for (i = 0; i < num; i++) { - if (hostapd_ip_diff(&nserv[i].addr, &oserv[i].addr) || - nserv[i].port != oserv[i].port || - nserv[i].shared_secret_len != oserv[i].shared_secret_len || - memcmp(nserv[i].shared_secret, oserv[i].shared_secret, - nserv[i].shared_secret_len) != 0) - return 1; - } - - return 0; -} - - -struct radius_client_data * -radius_client_reconfig(struct radius_client_data *old, void *ctx, - struct hostapd_radius_servers *oldconf, - struct hostapd_radius_servers *newconf) -{ - radius_client_flush(old, 0); - - if (newconf->retry_primary_interval != - oldconf->retry_primary_interval || - newconf->num_auth_servers != oldconf->num_auth_servers || - newconf->num_acct_servers != oldconf->num_acct_servers || - radius_servers_diff(newconf->auth_servers, oldconf->auth_servers, - newconf->num_auth_servers) || - radius_servers_diff(newconf->acct_servers, oldconf->acct_servers, - newconf->num_acct_servers)) { - hostapd_logger(ctx, NULL, HOSTAPD_MODULE_RADIUS, - HOSTAPD_LEVEL_DEBUG, - "Reconfiguring RADIUS client"); - radius_client_deinit(old); - return radius_client_init(ctx, newconf); - } - - return old; -} diff --git a/contrib/wpa_supplicant/radius_client.h b/contrib/wpa_supplicant/radius_client.h deleted file mode 100644 index df1ba1f9b209..000000000000 --- a/contrib/wpa_supplicant/radius_client.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * hostapd / RADIUS client - * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "config_types.h" - -struct radius_msg; - -struct hostapd_radius_server { - /* MIB prefix for shared variables: - * @ = radiusAuth or radiusAcc depending on the type of the server */ - struct hostapd_ip_addr addr; /* @ServerAddress */ - int port; /* @ClientServerPortNumber */ - u8 *shared_secret; - size_t shared_secret_len; - - /* Dynamic (not from configuration file) MIB data */ - int index; /* @ServerIndex */ - int round_trip_time; /* @ClientRoundTripTime; in hundredths of a - * second */ - u32 requests; /* @Client{Access,}Requests */ - u32 retransmissions; /* @Client{Access,}Retransmissions */ - u32 access_accepts; /* radiusAuthClientAccessAccepts */ - u32 access_rejects; /* radiusAuthClientAccessRejects */ - u32 access_challenges; /* radiusAuthClientAccessChallenges */ - u32 responses; /* radiusAccClientResponses */ - u32 malformed_responses; /* @ClientMalformed{Access,}Responses */ - u32 bad_authenticators; /* @ClientBadAuthenticators */ - u32 timeouts; /* @ClientTimeouts */ - u32 unknown_types; /* @ClientUnknownTypes */ - u32 packets_dropped; /* @ClientPacketsDropped */ - /* @ClientPendingRequests: length of hapd->radius->msgs for matching - * msg_type */ -}; - -struct hostapd_radius_servers { - /* RADIUS Authentication and Accounting servers in priority order */ - struct hostapd_radius_server *auth_servers, *auth_server; - int num_auth_servers; - struct hostapd_radius_server *acct_servers, *acct_server; - int num_acct_servers; - - int retry_primary_interval; - int acct_interim_interval; - - int msg_dumps; -}; - - -typedef enum { - RADIUS_AUTH, - RADIUS_ACCT, - RADIUS_ACCT_INTERIM /* used only with radius_client_send(); just like - * RADIUS_ACCT, but removes any pending interim - * RADIUS Accounting packages for the same STA - * before sending the new interim update */ -} RadiusType; - -typedef enum { - RADIUS_RX_PROCESSED, - RADIUS_RX_QUEUED, - RADIUS_RX_UNKNOWN, - 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, - 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, u8 *addr); -int radius_client_get_mib(struct radius_client_data *radius, char *buf, - size_t buflen); -struct radius_client_data * -radius_client_reconfig(struct radius_client_data *old, void *ctx, - struct hostapd_radius_servers *oldconf, - struct hostapd_radius_servers *newconf); - -#endif /* RADIUS_CLIENT_H */ diff --git a/contrib/wpa_supplicant/rc4.c b/contrib/wpa_supplicant/rc4.c deleted file mode 100644 index 8480cc55cea6..000000000000 --- a/contrib/wpa_supplicant/rc4.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * RC4 stream cipher - * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "rc4.h" - -#define S_SWAP(a,b) do { u8 t = S[a]; S[a] = S[b]; S[b] = t; } while(0) - -/** - * rc4 - 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 - * - * 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. - */ -void 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]; - } -} - - -/** - * rc4 - XOR RC4 stream to given data - * @buf: data to be XOR'ed with RC4 stream - * @len: buf length - * @key: RC4 key - * @key_len: RC4 key length - * - * Generate RC4 pseudo random stream for the given key and XOR this with the - * data buffer to perform RC4 encryption/decryption. - */ -void rc4(u8 *buf, size_t len, const u8 *key, size_t key_len) -{ - rc4_skip(key, key_len, 0, buf, len); -} diff --git a/contrib/wpa_supplicant/rc4.h b/contrib/wpa_supplicant/rc4.h deleted file mode 100644 index 01f13833ddc8..000000000000 --- a/contrib/wpa_supplicant/rc4.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * RC4 stream cipher - * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 RC4_H -#define RC4_H - -void rc4_skip(const u8 *key, size_t keylen, size_t skip, - u8 *data, size_t data_len); -void rc4(u8 *buf, size_t len, const u8 *key, size_t key_len); - -#endif /* RC4_H */ diff --git a/contrib/wpa_supplicant/rsa.c b/contrib/wpa_supplicant/rsa.c deleted file mode 100644 index bfc0d5222495..000000000000 --- a/contrib/wpa_supplicant/rsa.c +++ /dev/null @@ -1,359 +0,0 @@ -/* - * RSA - * Copyright (c) 2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "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/contrib/wpa_supplicant/rsa.h b/contrib/wpa_supplicant/rsa.h deleted file mode 100644 index ac50dfd69d3e..000000000000 --- a/contrib/wpa_supplicant/rsa.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * RSA - * Copyright (c) 2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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/contrib/wpa_supplicant/sha1.c b/contrib/wpa_supplicant/sha1.c deleted file mode 100644 index e53c8452ddd8..000000000000 --- a/contrib/wpa_supplicant/sha1.c +++ /dev/null @@ -1,726 +0,0 @@ -/* - * SHA1 hash implementation and interface functions - * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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" - - -/** - * 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) - */ -void 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; - } - - /* if key is longer than 64 bytes reset it to key = SHA1(key) */ - if (key_len > 64) { - sha1_vector(1, &key, &key_len, tk); - 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]; - } - sha1_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 SHA1 */ - _addr[0] = k_pad; - _len[0] = 64; - _addr[1] = mac; - _len[1] = SHA1_MAC_LEN; - 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) - */ -void hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len, - u8 *mac) -{ - 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 - * - * This function is used to derive new, cryptographically separate keys from a - * given key (e.g., PMK in IEEE 802.11i). - */ -void 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 zero = 0, counter = 0; - size_t pos, plen; - u8 hash[SHA1_MAC_LEN]; - size_t label_len = os_strlen(label); - const unsigned char *addr[4]; - size_t len[4]; - - addr[0] = (u8 *) label; - len[0] = label_len; - addr[1] = &zero; - len[1] = 1; - addr[2] = data; - len[2] = data_len; - addr[3] = &counter; - 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++; - } -} - - -/** - * 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 - * - * This function is used to derive new, cryptographically separate keys from a - * given key for EAP-FAST. T-PRF is defined in - * draft-cam-winget-eap-fast-02.txt, Appendix B. - */ -void 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; - 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; - } -} - - -/** - * 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(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(S1, L_S1, 3, MD5_addr, MD5_len, P_MD5); - MD5_pos = 0; - hmac_md5(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; -} - - -static void 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; - hmac_sha1_vector((u8 *) passphrase, passphrase_len, 2, addr, len, tmp); - os_memcpy(digest, tmp, SHA1_MAC_LEN); - - for (i = 1; i < iterations; i++) { - hmac_sha1((u8 *) passphrase, passphrase_len, tmp, SHA1_MAC_LEN, - tmp2); - os_memcpy(tmp, tmp2, SHA1_MAC_LEN); - for (j = 0; j < SHA1_MAC_LEN; j++) - digest[j] ^= tmp2[j]; - } -} - - -/** - * pbkdf2_sha1 - SHA1-based key derivation function (PBKDF2) for IEEE 802.11i - * @passphrase: ASCII passphrase - * @ssid: SSID - * @ssid_len: SSID length in bytes - * @interations: Number of iterations to run - * @buf: Buffer for the generated key - * @buflen: Length of the buffer in bytes - * - * 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. - */ -void 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++; - pbkdf2_sha1_f(passphrase, ssid, ssid_len, iterations, count, - digest); - plen = left > SHA1_MAC_LEN ? SHA1_MAC_LEN : left; - os_memcpy(pos, digest, plen); - pos += plen; - left -= plen; - } -} - - -#ifdef INTERNAL_SHA1 - -struct SHA1Context { - u32 state[5]; - u32 count[2]; - unsigned char buffer[64]; -}; - -typedef struct SHA1Context SHA1_CTX; - -#ifndef CONFIG_CRYPTO_INTERNAL -static void SHA1Init(struct SHA1Context *context); -static void SHA1Update(struct SHA1Context *context, const void *data, u32 len); -static void SHA1Final(unsigned char digest[20], struct SHA1Context *context); -#endif /* CONFIG_CRYPTO_INTERNAL */ -static 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 - */ -void 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); -} - - -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; -} - - -/* ===== start - public domain SHA1 implementation ===== */ - -/* -SHA-1 in C -By Steve Reid <sreid@sea-to-sky.net> -100% Public Domain - ------------------ -Modified 7/98 -By James H. Brown <jbrown@burgoyne.com> -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 <process.h> 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 <sreid@sea-to-sky.net> -Still 100% public domain - -1- Removed #include <process.h> 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 <Saul.Kravitz@celera.com> -Still 100% PD -Modified to run on Compaq Alpha hardware. - ------------------ -Modified 4/01 -By Jouni Malinen <j@w1.fi> -Minor changes to match the coding style used in Dynamics. - -Modified September 24, 2004 -By Jouni Malinen <j@w1.fi> -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. */ - -static 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 - u32 workspace[16]; - block = (CHAR64LONG16 *) 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 ===== */ - -#endif /* INTERNAL_SHA1 */ diff --git a/contrib/wpa_supplicant/sha1.h b/contrib/wpa_supplicant/sha1.h deleted file mode 100644 index 97affa1a620d..000000000000 --- a/contrib/wpa_supplicant/sha1.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * SHA1 hash implementation and interface functions - * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 - -void hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac); -void hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len, - u8 *mac); -void 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); -void 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 tls_prf(const u8 *secret, size_t secret_len, const char *label, - const u8 *seed, size_t seed_len, u8 *out, size_t outlen); -void pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len, - int iterations, u8 *buf, size_t buflen); - -#ifdef CONFIG_CRYPTO_INTERNAL -struct SHA1Context; - -void SHA1Init(struct SHA1Context *context); -void SHA1Update(struct SHA1Context *context, const void *data, u32 len); -void SHA1Final(unsigned char digest[20], struct SHA1Context *context); -#endif /* CONFIG_CRYPTO_INTERNAL */ - -#endif /* SHA1_H */ diff --git a/contrib/wpa_supplicant/sha256.c b/contrib/wpa_supplicant/sha256.c deleted file mode 100644 index 175ec8b637da..000000000000 --- a/contrib/wpa_supplicant/sha256.c +++ /dev/null @@ -1,379 +0,0 @@ -/* - * SHA-256 hash implementation and interface functions - * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 */ - memset(k_pad, 0, sizeof(k_pad)); - 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); - - memset(k_pad, 0, sizeof(k_pad)); - 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.5A.3) - * @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 = 0; - size_t pos, plen; - u8 hash[SHA256_MAC_LEN]; - const u8 *addr[3]; - size_t len[3]; - u8 counter_le[2]; - - addr[0] = counter_le; - len[0] = 2; - addr[1] = (u8 *) label; - len[1] = strlen(label) + 1; - addr[2] = data; - len[2] = data_len; - - 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, 3, addr, len, - &buf[pos]); - pos += SHA256_MAC_LEN; - } else { - hmac_sha256_vector(key, key_len, 3, addr, len, hash); - memcpy(&buf[pos], hash, plen); - break; - } - counter++; - } -} - - -#ifdef INTERNAL_SHA256 - -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 - */ -void 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++) - sha256_process(&ctx, addr[i], len[i]); - sha256_done(&ctx, mac); -} - - -/* ===== 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)); - 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 ===== */ - -#endif /* INTERNAL_SHA256 */ diff --git a/contrib/wpa_supplicant/sha256.h b/contrib/wpa_supplicant/sha256.h deleted file mode 100644 index dc597f09b53a..000000000000 --- a/contrib/wpa_supplicant/sha256.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * SHA256 hash implementation and interface functions - * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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/contrib/wpa_supplicant/state_machine.h b/contrib/wpa_supplicant/state_machine.h deleted file mode 100644 index 62766bf40ba4..000000000000 --- a/contrib/wpa_supplicant/state_machine.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * wpa_supplicant/hostapd - State machine definitions - * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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/contrib/wpa_supplicant/tests/test_aes.c b/contrib/wpa_supplicant/tests/test_aes.c deleted file mode 100644 index 09c2d8e3586e..000000000000 --- a/contrib/wpa_supplicant/tests/test_aes.c +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Test program for AES - * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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_wrap.h" - -#define BLOCK_SIZE 16 - -static void test_aes_perf(void) -{ -#if 0 /* this did not seem to work with new compiler?! */ -#ifdef __i386__ -#define rdtscll(val) \ - __asm__ __volatile__("rdtsc" : "=A" (val)) - const int num_iters = 10; - int i; - unsigned int start, end; - u8 key[16], pt[16], ct[16]; - void *ctx; - - printf("keySetupEnc:"); - for (i = 0; i < num_iters; i++) { - rdtscll(start); - ctx = aes_encrypt_init(key, 16); - rdtscll(end); - aes_encrypt_deinit(ctx); - printf(" %d", end - start); - } - printf("\n"); - - printf("Encrypt:"); - ctx = aes_encrypt_init(key, 16); - for (i = 0; i < num_iters; i++) { - rdtscll(start); - aes_encrypt(ctx, pt, ct); - rdtscll(end); - printf(" %d", end - start); - } - aes_encrypt_deinit(ctx); - printf("\n"); -#endif /* __i386__ */ -#endif -} - - -static int test_eax(void) -{ - u8 msg[] = { 0xF7, 0xFB }; - u8 key[] = { 0x91, 0x94, 0x5D, 0x3F, 0x4D, 0xCB, 0xEE, 0x0B, - 0xF4, 0x5E, 0xF5, 0x22, 0x55, 0xF0, 0x95, 0xA4 }; - u8 nonce[] = { 0xBE, 0xCA, 0xF0, 0x43, 0xB0, 0xA2, 0x3D, 0x84, - 0x31, 0x94, 0xBA, 0x97, 0x2C, 0x66, 0xDE, 0xBD }; - u8 hdr[] = { 0xFA, 0x3B, 0xFD, 0x48, 0x06, 0xEB, 0x53, 0xFA }; - u8 cipher[] = { 0x19, 0xDD, 0x5C, 0x4C, 0x93, 0x31, 0x04, 0x9D, - 0x0B, 0xDA, 0xB0, 0x27, 0x74, 0x08, 0xF6, 0x79, - 0x67, 0xE5 }; - u8 data[sizeof(msg)], tag[BLOCK_SIZE]; - - memcpy(data, msg, sizeof(msg)); - if (aes_128_eax_encrypt(key, nonce, sizeof(nonce), hdr, sizeof(hdr), - data, sizeof(data), tag)) { - printf("AES-128 EAX mode encryption failed\n"); - return 1; - } - if (memcmp(data, cipher, sizeof(data)) != 0) { - printf("AES-128 EAX mode encryption returned invalid cipher " - "text\n"); - return 1; - } - if (memcmp(tag, cipher + sizeof(data), BLOCK_SIZE) != 0) { - printf("AES-128 EAX mode encryption returned invalid tag\n"); - return 1; - } - - if (aes_128_eax_decrypt(key, nonce, sizeof(nonce), hdr, sizeof(hdr), - data, sizeof(data), tag)) { - printf("AES-128 EAX mode decryption failed\n"); - return 1; - } - if (memcmp(data, msg, sizeof(data)) != 0) { - printf("AES-128 EAX mode decryption returned invalid plain " - "text\n"); - return 1; - } - - return 0; -} - - -static int test_cbc(void) -{ - struct cbc_test_vector { - u8 key[16]; - u8 iv[16]; - u8 plain[32]; - u8 cipher[32]; - size_t len; - } vectors[] = { - { - { 0x06, 0xa9, 0x21, 0x40, 0x36, 0xb8, 0xa1, 0x5b, - 0x51, 0x2e, 0x03, 0xd5, 0x34, 0x12, 0x00, 0x06 }, - { 0x3d, 0xaf, 0xba, 0x42, 0x9d, 0x9e, 0xb4, 0x30, - 0xb4, 0x22, 0xda, 0x80, 0x2c, 0x9f, 0xac, 0x41 }, - "Single block msg", - { 0xe3, 0x53, 0x77, 0x9c, 0x10, 0x79, 0xae, 0xb8, - 0x27, 0x08, 0x94, 0x2d, 0xbe, 0x77, 0x18, 0x1a }, - 16 - }, - { - { 0xc2, 0x86, 0x69, 0x6d, 0x88, 0x7c, 0x9a, 0xa0, - 0x61, 0x1b, 0xbb, 0x3e, 0x20, 0x25, 0xa4, 0x5a }, - { 0x56, 0x2e, 0x17, 0x99, 0x6d, 0x09, 0x3d, 0x28, - 0xdd, 0xb3, 0xba, 0x69, 0x5a, 0x2e, 0x6f, 0x58 }, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, - { 0xd2, 0x96, 0xcd, 0x94, 0xc2, 0xcc, 0xcf, 0x8a, - 0x3a, 0x86, 0x30, 0x28, 0xb5, 0xe1, 0xdc, 0x0a, - 0x75, 0x86, 0x60, 0x2d, 0x25, 0x3c, 0xff, 0xf9, - 0x1b, 0x82, 0x66, 0xbe, 0xa6, 0xd6, 0x1a, 0xb1 }, - 32 - } - }; - int ret = 0; - u8 *buf; - unsigned int i; - - for (i = 0; i < sizeof(vectors) / sizeof(vectors[0]); i++) { - struct cbc_test_vector *tv = &vectors[i]; - buf = malloc(tv->len); - if (buf == NULL) { - ret++; - break; - } - memcpy(buf, tv->plain, tv->len); - aes_128_cbc_encrypt(tv->key, tv->iv, buf, tv->len); - if (memcmp(buf, tv->cipher, tv->len) != 0) { - printf("AES-CBC encrypt %d failed\n", i); - ret++; - } - memcpy(buf, tv->cipher, tv->len); - aes_128_cbc_decrypt(tv->key, tv->iv, buf, tv->len); - if (memcmp(buf, tv->plain, tv->len) != 0) { - printf("AES-CBC decrypt %d failed\n", i); - ret++; - } - free(buf); - } - - return ret; -} - - -/* OMAC1 AES-128 test vectors from - * http://csrc.nist.gov/CryptoToolkit/modes/proposedmodes/omac/omac-ad.pdf - */ - -struct omac1_test_vector { - u8 k[16]; - u8 msg[64]; - int msg_len; - u8 tag[16]; -}; - -static struct omac1_test_vector test_vectors[] = -{ - { - { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, - 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, - { }, - 0, - { 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, - 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46 } - }, - { - { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, - 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, - { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, - 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a}, - 16, - { 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, - 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c } - }, - { - { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, - 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, - { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, - 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, - 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, - 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, - 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11 }, - 40, - { 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30, - 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27 } - }, - { - { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, - 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, - { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, - 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, - 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, - 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, - 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, - 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, - 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, - 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 }, - 64, - { 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, - 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe } - }, -}; - - -int main(int argc, char *argv[]) -{ - u8 kek[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f - }; - u8 plain[] = { - 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, - 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff - }; - u8 crypt[] = { - 0x1F, 0xA6, 0x8B, 0x0A, 0x81, 0x12, 0xB4, 0x47, - 0xAE, 0xF3, 0x4B, 0xD8, 0xFB, 0x5A, 0x7B, 0x82, - 0x9D, 0x3E, 0x86, 0x23, 0x71, 0xD2, 0xCF, 0xE5 - }; - u8 result[24]; - int ret = 0; - unsigned int i; - struct omac1_test_vector *tv; - - if (aes_wrap(kek, 2, plain, result)) { - printf("AES-WRAP-128-128 reported failure\n"); - ret++; - } - if (memcmp(result, crypt, 24) != 0) { - printf("AES-WRAP-128-128 failed\n"); - ret++; - } - if (aes_unwrap(kek, 2, crypt, result)) { - printf("AES-UNWRAP-128-128 reported failure\n"); - ret++; - } - if (memcmp(result, plain, 16) != 0) { - int i; - printf("AES-UNWRAP-128-128 failed\n"); - ret++; - for (i = 0; i < 16; i++) - printf(" %02x", result[i]); - printf("\n"); - } - - test_aes_perf(); - - for (i = 0; i < sizeof(test_vectors) / sizeof(test_vectors[0]); i++) { - tv = &test_vectors[i]; - omac1_aes_128(tv->k, tv->msg, tv->msg_len, result); - if (memcmp(result, tv->tag, 16) != 0) { - printf("OMAC1-AES-128 test vector %d failed\n", i); - ret++; - } - - if (tv->msg_len > 1) { - const u8 *addr[2]; - size_t len[2]; - - addr[0] = tv->msg; - len[0] = 1; - addr[1] = tv->msg + 1; - len[1] = tv->msg_len - 1; - - omac1_aes_128_vector(tv->k, 2, addr, len, result); - if (memcmp(result, tv->tag, 16) != 0) { - printf("OMAC1-AES-128(vector) test vector %d " - "failed\n", i); - ret++; - } - } - } - - ret += test_eax(); - - ret += test_cbc(); - - if (ret) - printf("FAILED!\n"); - - return ret; -} diff --git a/contrib/wpa_supplicant/tests/test_eap_sim_common.c b/contrib/wpa_supplicant/tests/test_eap_sim_common.c deleted file mode 100644 index ee3eee4d2911..000000000000 --- a/contrib/wpa_supplicant/tests/test_eap_sim_common.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Test program for EAP-SIM PRF - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "eap_sim_common.c" - - -static int test_eap_sim_prf(void) -{ - /* http://csrc.nist.gov/encryption/dss/Examples-1024bit.pdf */ - u8 xkey[] = { - 0xbd, 0x02, 0x9b, 0xbe, 0x7f, 0x51, 0x96, 0x0b, - 0xcf, 0x9e, 0xdb, 0x2b, 0x61, 0xf0, 0x6f, 0x0f, - 0xeb, 0x5a, 0x38, 0xb6 - }; - u8 w[] = { - 0x20, 0x70, 0xb3, 0x22, 0x3d, 0xba, 0x37, 0x2f, - 0xde, 0x1c, 0x0f, 0xfc, 0x7b, 0x2e, 0x3b, 0x49, - 0x8b, 0x26, 0x06, 0x14, 0x3c, 0x6c, 0x18, 0xba, - 0xcb, 0x0f, 0x6c, 0x55, 0xba, 0xbb, 0x13, 0x78, - 0x8e, 0x20, 0xd7, 0x37, 0xa3, 0x27, 0x51, 0x16 - }; - u8 buf[40]; - - printf("Testing EAP-SIM PRF (FIPS 186-2 + change notice 1)\n"); - eap_sim_prf(xkey, buf, sizeof(buf)); - if (memcmp(w, buf, sizeof(w) != 0)) { - printf("eap_sim_prf failed\n"); - return 1; - } - - return 0; -} - - -int main(int argc, char *argv[]) -{ - int errors = 0; - - errors += test_eap_sim_prf(); - - return errors; -} diff --git a/contrib/wpa_supplicant/tests/test_md4.c b/contrib/wpa_supplicant/tests/test_md4.c deleted file mode 100644 index e92e9a5fafdd..000000000000 --- a/contrib/wpa_supplicant/tests/test_md4.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Test program for MD4 (test vectors from RFC 1320) - * Copyright (c) 2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 main(int argc, char *argv[]) -{ - struct { - char *data; - u8 *hash; - } tests[] = { - { - "", - "\x31\xd6\xcf\xe0\xd1\x6a\xe9\x31" - "\xb7\x3c\x59\xd7\xe0\xc0\x89\xc0" - }, - { - "a", - "\xbd\xe5\x2c\xb3\x1d\xe3\x3e\x46" - "\x24\x5e\x05\xfb\xdb\xd6\xfb\x24" - }, - { - "abc", - "\xa4\x48\x01\x7a\xaf\x21\xd8\x52" - "\x5f\xc1\x0a\xe8\x7a\xa6\x72\x9d" - }, - { - "message digest", - "\xd9\x13\x0a\x81\x64\x54\x9f\xe8" - "\x18\x87\x48\x06\xe1\xc7\x01\x4b" - }, - { - "abcdefghijklmnopqrstuvwxyz", - "\xd7\x9e\x1c\x30\x8a\xa5\xbb\xcd" - "\xee\xa8\xed\x63\xdf\x41\x2d\xa9" - }, - { - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" - "0123456789", - "\x04\x3f\x85\x82\xf2\x41\xdb\x35" - "\x1c\xe6\x27\xe1\x53\xe7\xf0\xe4" - }, - { - "12345678901234567890123456789012345678901234567890" - "123456789012345678901234567890", - "\xe3\x3b\x4d\xdc\x9c\x38\xf2\x19" - "\x9c\x3e\x7b\x16\x4f\xcc\x05\x36" - } - }; - unsigned int i; - u8 hash[16]; - const u8 *addr[2]; - size_t len[2]; - int errors = 0; - - for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { - printf("MD4 test case %d:", i); - - addr[0] = tests[i].data; - len[0] = strlen(tests[i].data); - md4_vector(1, addr, len, hash); - if (memcmp(hash, tests[i].hash, 16) != 0) { - printf(" FAIL"); - errors++; - } else - printf(" OK"); - - if (len[0]) { - addr[0] = tests[i].data; - len[0] = strlen(tests[i].data); - addr[1] = tests[i].data + 1; - len[1] = strlen(tests[i].data) - 1; - md4_vector(1, addr, len, hash); - if (memcmp(hash, tests[i].hash, 16) != 0) { - printf(" FAIL"); - errors++; - } else - printf(" OK"); - } - - printf("\n"); - } - - return errors; -} diff --git a/contrib/wpa_supplicant/tests/test_md5.c b/contrib/wpa_supplicant/tests/test_md5.c deleted file mode 100644 index d8fb41ef694e..000000000000 --- a/contrib/wpa_supplicant/tests/test_md5.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Test program for MD5 (test vectors from RFC 1321) - * Copyright (c) 2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 main(int argc, char *argv[]) -{ - struct { - char *data; - u8 *hash; - } tests[] = { - { - "", - "\xd4\x1d\x8c\xd9\x8f\x00\xb2\x04" - "\xe9\x80\x09\x98\xec\xf8\x42\x7e" - }, - { - "a", - "\x0c\xc1\x75\xb9\xc0\xf1\xb6\xa8" - "\x31\xc3\x99\xe2\x69\x77\x26\x61" - }, - { - "abc", - "\x90\x01\x50\x98\x3c\xd2\x4f\xb0" - "\xd6\x96\x3f\x7d\x28\xe1\x7f\x72" - }, - { - "message digest", - "\xf9\x6b\x69\x7d\x7c\xb7\x93\x8d" - "\x52\x5a\x2f\x31\xaa\xf1\x61\xd0" - }, - { - "abcdefghijklmnopqrstuvwxyz", - "\xc3\xfc\xd3\xd7\x61\x92\xe4\x00" - "\x7d\xfb\x49\x6c\xca\x67\xe1\x3b" - }, - { - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" - "0123456789", - "\xd1\x74\xab\x98\xd2\x77\xd9\xf5" - "\xa5\x61\x1c\x2c\x9f\x41\x9d\x9f" - }, - { - "12345678901234567890123456789012345678901234567890" - "123456789012345678901234567890", - "\x57\xed\xf4\xa2\x2b\xe3\xc9\x55" - "\xac\x49\xda\x2e\x21\x07\xb6\x7a" - } - }; - unsigned int i; - u8 hash[16]; - const u8 *addr[2]; - size_t len[2]; - int errors = 0; - - for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { - printf("MD5 test case %d:", i); - - addr[0] = tests[i].data; - len[0] = strlen(tests[i].data); - md5_vector(1, addr, len, hash); - if (memcmp(hash, tests[i].hash, 16) != 0) { - printf(" FAIL"); - errors++; - } else - printf(" OK"); - - if (len[0]) { - addr[0] = tests[i].data; - len[0] = strlen(tests[i].data); - addr[1] = tests[i].data + 1; - len[1] = strlen(tests[i].data) - 1; - md5_vector(1, addr, len, hash); - if (memcmp(hash, tests[i].hash, 16) != 0) { - printf(" FAIL"); - errors++; - } else - printf(" OK"); - } - - printf("\n"); - } - - return errors; -} diff --git a/contrib/wpa_supplicant/tests/test_ms_funcs.c b/contrib/wpa_supplicant/tests/test_ms_funcs.c deleted file mode 100644 index 09b53c46f34f..000000000000 --- a/contrib/wpa_supplicant/tests/test_ms_funcs.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Test program for ms_funcs - * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "ms_funcs.c" - - -int main(int argc, char *argv[]) -{ - /* Test vector from RFC2759 example */ - u8 *username = "User"; - u8 *password = "clientPass"; - u8 auth_challenge[] = { - 0x5B, 0x5D, 0x7C, 0x7D, 0x7B, 0x3F, 0x2F, 0x3E, - 0x3C, 0x2C, 0x60, 0x21, 0x32, 0x26, 0x26, 0x28 - }; - u8 peer_challenge[] = { - 0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, - 0x28, 0x29, 0x5F, 0x2B, 0x3A, 0x33, 0x7C, 0x7E - }; - u8 challenge[] = { 0xD0, 0x2E, 0x43, 0x86, 0xBC, 0xE9, 0x12, 0x26 }; - u8 password_hash[] = { - 0x44, 0xEB, 0xBA, 0x8D, 0x53, 0x12, 0xB8, 0xD6, - 0x11, 0x47, 0x44, 0x11, 0xF5, 0x69, 0x89, 0xAE - }; - u8 nt_response[] = { - 0x82, 0x30, 0x9E, 0xCD, 0x8D, 0x70, 0x8B, 0x5E, - 0xA0, 0x8F, 0xAA, 0x39, 0x81, 0xCD, 0x83, 0x54, - 0x42, 0x33, 0x11, 0x4A, 0x3D, 0x85, 0xD6, 0xDF - }; - u8 password_hash_hash[] = { - 0x41, 0xC0, 0x0C, 0x58, 0x4B, 0xD2, 0xD9, 0x1C, - 0x40, 0x17, 0xA2, 0xA1, 0x2F, 0xA5, 0x9F, 0x3F - }; - u8 authenticator_response[] = { - 0x40, 0x7A, 0x55, 0x89, 0x11, 0x5F, 0xD0, 0xD6, - 0x20, 0x9F, 0x51, 0x0F, 0xE9, 0xC0, 0x45, 0x66, - 0x93, 0x2C, 0xDA, 0x56 - }; - u8 master_key[] = { - 0xFD, 0xEC, 0xE3, 0x71, 0x7A, 0x8C, 0x83, 0x8C, - 0xB3, 0x88, 0xE5, 0x27, 0xAE, 0x3C, 0xDD, 0x31 - }; - u8 send_start_key[] = { - 0x8B, 0x7C, 0xDC, 0x14, 0x9B, 0x99, 0x3A, 0x1B, - 0xA1, 0x18, 0xCB, 0x15, 0x3F, 0x56, 0xDC, 0xCB - }; - u8 buf[32]; - - int errors = 0; - - printf("Testing ms_funcs.c\n"); - - challenge_hash(peer_challenge, auth_challenge, - username, strlen(username), - buf); - if (memcmp(challenge, buf, sizeof(challenge)) != 0) { - printf("challenge_hash failed\n"); - errors++; - } - - nt_password_hash(password, strlen(password), buf); - if (memcmp(password_hash, buf, sizeof(password_hash)) != 0) { - printf("nt_password_hash failed\n"); - errors++; - } - - generate_nt_response(auth_challenge, peer_challenge, - username, strlen(username), - password, strlen(password), - buf); - if (memcmp(nt_response, buf, sizeof(nt_response)) != 0) { - printf("generate_nt_response failed\n"); - errors++; - } - - hash_nt_password_hash(password_hash, buf); - if (memcmp(password_hash_hash, buf, sizeof(password_hash_hash)) != 0) { - printf("hash_nt_password_hash failed\n"); - errors++; - } - - generate_authenticator_response(password, strlen(password), - peer_challenge, auth_challenge, - username, strlen(username), - nt_response, buf); - if (memcmp(authenticator_response, buf, sizeof(authenticator_response)) - != 0) { - printf("generate_authenticator_response failed\n"); - errors++; - } - - get_master_key(password_hash_hash, nt_response, buf); - if (memcmp(master_key, buf, sizeof(master_key)) != 0) { - printf("get_master_key failed\n"); - errors++; - } - - get_asymetric_start_key(master_key, buf, sizeof(send_start_key), 1, 1); - if (memcmp(send_start_key, buf, sizeof(send_start_key)) != 0) { - printf("get_asymetric_start_key failed\n"); - errors++; - } - - if (errors) - printf("FAILED! %d errors\n", errors); - - return errors; -} diff --git a/contrib/wpa_supplicant/tests/test_sha1.c b/contrib/wpa_supplicant/tests/test_sha1.c deleted file mode 100644 index a34e3bf4bbc1..000000000000 --- a/contrib/wpa_supplicant/tests/test_sha1.c +++ /dev/null @@ -1,328 +0,0 @@ -/* - * Test program for SHA1 and MD5 - * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 test_eap_fast(void) -{ - /* draft-cam-winget-eap-fast-01.txt */ - const u8 pac_key[] = { - 0x0B, 0x97, 0x39, 0x0F, 0x37, 0x51, 0x78, 0x09, - 0x81, 0x1E, 0xFD, 0x9C, 0x6E, 0x65, 0x94, 0x2B, - 0x63, 0x2C, 0xE9, 0x53, 0x89, 0x38, 0x08, 0xBA, - 0x36, 0x0B, 0x03, 0x7C, 0xD1, 0x85, 0xE4, 0x14 - }; - const u8 seed[] = { - 0x3F, 0xFB, 0x11, 0xC4, 0x6C, 0xBF, 0xA5, 0x7A, - 0x54, 0x40, 0xDA, 0xE8, 0x22, 0xD3, 0x11, 0xD3, - 0xF7, 0x6D, 0xE4, 0x1D, 0xD9, 0x33, 0xE5, 0x93, - 0x70, 0x97, 0xEB, 0xA9, 0xB3, 0x66, 0xF4, 0x2A, - 0x00, 0x00, 0x00, 0x02, 0x6A, 0x66, 0x43, 0x2A, - 0x8D, 0x14, 0x43, 0x2C, 0xEC, 0x58, 0x2D, 0x2F, - 0xC7, 0x9C, 0x33, 0x64, 0xBA, 0x04, 0xAD, 0x3A, - 0x52, 0x54, 0xD6, 0xA5, 0x79, 0xAD, 0x1E, 0x00 - }; - const u8 master_secret[] = { - 0x4A, 0x1A, 0x51, 0x2C, 0x01, 0x60, 0xBC, 0x02, - 0x3C, 0xCF, 0xBC, 0x83, 0x3F, 0x03, 0xBC, 0x64, - 0x88, 0xC1, 0x31, 0x2F, 0x0B, 0xA9, 0xA2, 0x77, - 0x16, 0xA8, 0xD8, 0xE8, 0xBD, 0xC9, 0xD2, 0x29, - 0x38, 0x4B, 0x7A, 0x85, 0xBE, 0x16, 0x4D, 0x27, - 0x33, 0xD5, 0x24, 0x79, 0x87, 0xB1, 0xC5, 0xA2 - }; - const u8 key_block[] = { - 0x59, 0x59, 0xBE, 0x8E, 0x41, 0x3A, 0x77, 0x74, - 0x8B, 0xB2, 0xE5, 0xD3, 0x60, 0xAC, 0x4D, 0x35, - 0xDF, 0xFB, 0xC8, 0x1E, 0x9C, 0x24, 0x9C, 0x8B, - 0x0E, 0xC3, 0x1D, 0x72, 0xC8, 0x84, 0x9D, 0x57, - 0x48, 0x51, 0x2E, 0x45, 0x97, 0x6C, 0x88, 0x70, - 0xBE, 0x5F, 0x01, 0xD3, 0x64, 0xE7, 0x4C, 0xBB, - 0x11, 0x24, 0xE3, 0x49, 0xE2, 0x3B, 0xCD, 0xEF, - 0x7A, 0xB3, 0x05, 0x39, 0x5D, 0x64, 0x8A, 0x44, - 0x11, 0xB6, 0x69, 0x88, 0x34, 0x2E, 0x8E, 0x29, - 0xD6, 0x4B, 0x7D, 0x72, 0x17, 0x59, 0x28, 0x05, - 0xAF, 0xF9, 0xB7, 0xFF, 0x66, 0x6D, 0xA1, 0x96, - 0x8F, 0x0B, 0x5E, 0x06, 0x46, 0x7A, 0x44, 0x84, - 0x64, 0xC1, 0xC8, 0x0C, 0x96, 0x44, 0x09, 0x98, - 0xFF, 0x92, 0xA8, 0xB4, 0xC6, 0x42, 0x28, 0x71 - }; - const u8 sks[] = { - 0xD6, 0x4B, 0x7D, 0x72, 0x17, 0x59, 0x28, 0x05, - 0xAF, 0xF9, 0xB7, 0xFF, 0x66, 0x6D, 0xA1, 0x96, - 0x8F, 0x0B, 0x5E, 0x06, 0x46, 0x7A, 0x44, 0x84, - 0x64, 0xC1, 0xC8, 0x0C, 0x96, 0x44, 0x09, 0x98, - 0xFF, 0x92, 0xA8, 0xB4, 0xC6, 0x42, 0x28, 0x71 - }; - const u8 isk[] = { - 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 - }; - const u8 imck[] = { - 0x16, 0x15, 0x3C, 0x3F, 0x21, 0x55, 0xEF, 0xD9, - 0x7F, 0x34, 0xAE, 0xC8, 0x1A, 0x4E, 0x66, 0x80, - 0x4C, 0xC3, 0x76, 0xF2, 0x8A, 0xA9, 0x6F, 0x96, - 0xC2, 0x54, 0x5F, 0x8C, 0xAB, 0x65, 0x02, 0xE1, - 0x18, 0x40, 0x7B, 0x56, 0xBE, 0xEA, 0xA7, 0xC5, - 0x76, 0x5D, 0x8F, 0x0B, 0xC5, 0x07, 0xC6, 0xB9, - 0x04, 0xD0, 0x69, 0x56, 0x72, 0x8B, 0x6B, 0xB8, - 0x15, 0xEC, 0x57, 0x7B - }; - const u8 msk[] = { - 0x4D, 0x83, 0xA9, 0xBE, 0x6F, 0x8A, 0x74, 0xED, - 0x6A, 0x02, 0x66, 0x0A, 0x63, 0x4D, 0x2C, 0x33, - 0xC2, 0xDA, 0x60, 0x15, 0xC6, 0x37, 0x04, 0x51, - 0x90, 0x38, 0x63, 0xDA, 0x54, 0x3E, 0x14, 0xB9, - 0x27, 0x99, 0x18, 0x1E, 0x07, 0xBF, 0x0F, 0x5A, - 0x5E, 0x3C, 0x32, 0x93, 0x80, 0x8C, 0x6C, 0x49, - 0x67, 0xED, 0x24, 0xFE, 0x45, 0x40, 0xA0, 0x59, - 0x5E, 0x37, 0xC2, 0xE9, 0xD0, 0x5D, 0x0A, 0xE3 - }; - u8 tlv[] = { - 0x80, 0x0C, 0x00, 0x38, 0x00, 0x01, 0x01, 0x00, - 0xD8, 0x6A, 0x8C, 0x68, 0x3C, 0x32, 0x31, 0xA8, - 0x56, 0x63, 0xB6, 0x40, 0x21, 0xFE, 0x21, 0x14, - 0x4E, 0xE7, 0x54, 0x20, 0x79, 0x2D, 0x42, 0x62, - 0xC9, 0xBF, 0x53, 0x7F, 0x54, 0xFD, 0xAC, 0x58, - 0x43, 0x24, 0x6E, 0x30, 0x92, 0x17, 0x6D, 0xCF, - 0xE6, 0xE0, 0x69, 0xEB, 0x33, 0x61, 0x6A, 0xCC, - 0x05, 0xC5, 0x5B, 0xB7 - }; - const u8 compound_mac[] = { - 0x43, 0x24, 0x6E, 0x30, 0x92, 0x17, 0x6D, 0xCF, - 0xE6, 0xE0, 0x69, 0xEB, 0x33, 0x61, 0x6A, 0xCC, - 0x05, 0xC5, 0x5B, 0xB7 - }; - u8 buf[512]; - const u8 *simck, *cmk; - int errors = 0; - - printf("EAP-FAST test cases\n"); - - printf("- T-PRF (SHA1) test case / master_secret\n"); - sha1_t_prf(pac_key, sizeof(pac_key), "PAC to master secret label hash", - seed, sizeof(seed), buf, sizeof(master_secret)); - if (memcmp(master_secret, buf, sizeof(master_secret)) != 0) { - printf("T-PRF test - FAILED!\n"); - errors++; - } - - printf("- PRF (TLS, SHA1/MD5) test case / key_block\n"); - tls_prf(master_secret, sizeof(master_secret), "key expansion", - seed, sizeof(seed), buf, sizeof(key_block)); - if (memcmp(key_block, buf, sizeof(key_block)) != 0) { - printf("PRF test - FAILED!\n"); - errors++; - } - - printf("- T-PRF (SHA1) test case / IMCK\n"); - sha1_t_prf(sks, sizeof(sks), "Inner Methods Compound Keys", - isk, sizeof(isk), buf, sizeof(imck)); - if (memcmp(imck, buf, sizeof(imck)) != 0) { - printf("T-PRF test - FAILED!\n"); - errors++; - } - - simck = imck; - cmk = imck + 40; - - printf("- T-PRF (SHA1) test case / MSK\n"); - sha1_t_prf(simck, 40, "Session Key Generating Function", - (u8 *) "", 0, buf, sizeof(msk)); - if (memcmp(msk, buf, sizeof(msk)) != 0) { - printf("T-PRF test - FAILED!\n"); - errors++; - } - - printf("- Compound MAC test case\n"); - memset(tlv + sizeof(tlv) - 20, 0, 20); - hmac_sha1(cmk, 20, tlv, sizeof(tlv), tlv + sizeof(tlv) - 20); - if (memcmp(tlv + sizeof(tlv) - 20, compound_mac, sizeof(compound_mac)) - != 0) { - printf("Compound MAC test - FAILED!\n"); - errors++; - } - - return errors; -} - - -static u8 key0[] = -{ - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b -}; -static u8 data0[] = "Hi There"; -static u8 prf0[] = -{ - 0xbc, 0xd4, 0xc6, 0x50, 0xb3, 0x0b, 0x96, 0x84, - 0x95, 0x18, 0x29, 0xe0, 0xd7, 0x5f, 0x9d, 0x54, - 0xb8, 0x62, 0x17, 0x5e, 0xd9, 0xf0, 0x06, 0x06, - 0xe1, 0x7d, 0x8d, 0xa3, 0x54, 0x02, 0xff, 0xee, - 0x75, 0xdf, 0x78, 0xc3, 0xd3, 0x1e, 0x0f, 0x88, - 0x9f, 0x01, 0x21, 0x20, 0xc0, 0x86, 0x2b, 0xeb, - 0x67, 0x75, 0x3e, 0x74, 0x39, 0xae, 0x24, 0x2e, - 0xdb, 0x83, 0x73, 0x69, 0x83, 0x56, 0xcf, 0x5a -}; - -static u8 key1[] = "Jefe"; -static u8 data1[] = "what do ya want for nothing?"; -static u8 prf1[] = -{ - 0x51, 0xf4, 0xde, 0x5b, 0x33, 0xf2, 0x49, 0xad, - 0xf8, 0x1a, 0xeb, 0x71, 0x3a, 0x3c, 0x20, 0xf4, - 0xfe, 0x63, 0x14, 0x46, 0xfa, 0xbd, 0xfa, 0x58, - 0x24, 0x47, 0x59, 0xae, 0x58, 0xef, 0x90, 0x09, - 0xa9, 0x9a, 0xbf, 0x4e, 0xac, 0x2c, 0xa5, 0xfa, - 0x87, 0xe6, 0x92, 0xc4, 0x40, 0xeb, 0x40, 0x02, - 0x3e, 0x7b, 0xab, 0xb2, 0x06, 0xd6, 0x1d, 0xe7, - 0xb9, 0x2f, 0x41, 0x52, 0x90, 0x92, 0xb8, 0xfc -}; - - -static u8 key2[] = -{ - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa -}; -static u8 data2[] = -{ - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd -}; -static u8 prf2[] = -{ - 0xe1, 0xac, 0x54, 0x6e, 0xc4, 0xcb, 0x63, 0x6f, - 0x99, 0x76, 0x48, 0x7b, 0xe5, 0xc8, 0x6b, 0xe1, - 0x7a, 0x02, 0x52, 0xca, 0x5d, 0x8d, 0x8d, 0xf1, - 0x2c, 0xfb, 0x04, 0x73, 0x52, 0x52, 0x49, 0xce, - 0x9d, 0xd8, 0xd1, 0x77, 0xea, 0xd7, 0x10, 0xbc, - 0x9b, 0x59, 0x05, 0x47, 0x23, 0x91, 0x07, 0xae, - 0xf7, 0xb4, 0xab, 0xd4, 0x3d, 0x87, 0xf0, 0xa6, - 0x8f, 0x1c, 0xbd, 0x9e, 0x2b, 0x6f, 0x76, 0x07 -}; - - -struct passphrase_test { - char *passphrase; - char *ssid; - char psk[32]; -}; - -static struct passphrase_test passphrase_tests[] = -{ - { - "password", - "IEEE", - { - 0xf4, 0x2c, 0x6f, 0xc5, 0x2d, 0xf0, 0xeb, 0xef, - 0x9e, 0xbb, 0x4b, 0x90, 0xb3, 0x8a, 0x5f, 0x90, - 0x2e, 0x83, 0xfe, 0x1b, 0x13, 0x5a, 0x70, 0xe2, - 0x3a, 0xed, 0x76, 0x2e, 0x97, 0x10, 0xa1, 0x2e - } - }, - { - "ThisIsAPassword", - "ThisIsASSID", - { - 0x0d, 0xc0, 0xd6, 0xeb, 0x90, 0x55, 0x5e, 0xd6, - 0x41, 0x97, 0x56, 0xb9, 0xa1, 0x5e, 0xc3, 0xe3, - 0x20, 0x9b, 0x63, 0xdf, 0x70, 0x7d, 0xd5, 0x08, - 0xd1, 0x45, 0x81, 0xf8, 0x98, 0x27, 0x21, 0xaf - } - }, - { - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ", - { - 0xbe, 0xcb, 0x93, 0x86, 0x6b, 0xb8, 0xc3, 0x83, - 0x2c, 0xb7, 0x77, 0xc2, 0xf5, 0x59, 0x80, 0x7c, - 0x8c, 0x59, 0xaf, 0xcb, 0x6e, 0xae, 0x73, 0x48, - 0x85, 0x00, 0x13, 0x00, 0xa9, 0x81, 0xcc, 0x62 - } - }, -}; - -#define NUM_PASSPHRASE_TESTS \ -(sizeof(passphrase_tests) / sizeof(passphrase_tests[0])) - - -int main(int argc, char *argv[]) -{ - u8 res[512]; - int ret = 0; - unsigned int i; - - printf("PRF-SHA1 test cases:\n"); - - sha1_prf(key0, sizeof(key0), "prefix", data0, sizeof(data0) - 1, - res, sizeof(prf0)); - if (memcmp(res, prf0, sizeof(prf0)) == 0) - printf("Test case 0 - OK\n"); - else { - printf("Test case 0 - FAILED!\n"); - ret++; - } - - sha1_prf(key1, sizeof(key1) - 1, "prefix", data1, sizeof(data1) - 1, - res, sizeof(prf1)); - if (memcmp(res, prf1, sizeof(prf1)) == 0) - printf("Test case 1 - OK\n"); - else { - printf("Test case 1 - FAILED!\n"); - ret++; - } - - sha1_prf(key2, sizeof(key2), "prefix", data2, sizeof(data2), - res, sizeof(prf2)); - if (memcmp(res, prf2, sizeof(prf2)) == 0) - printf("Test case 2 - OK\n"); - else { - printf("Test case 2 - FAILED!\n"); - ret++; - } - - ret += test_eap_fast(); - - printf("PBKDF2-SHA1 Passphrase test cases:\n"); - for (i = 0; i < NUM_PASSPHRASE_TESTS; i++) { - u8 psk[32]; - struct passphrase_test *test = &passphrase_tests[i]; - pbkdf2_sha1(test->passphrase, - test->ssid, strlen(test->ssid), - 4096, psk, 32); - if (memcmp(psk, test->psk, 32) == 0) - printf("Test case %d - OK\n", i); - else { - printf("Test case %d - FAILED!\n", i); - ret++; - } - } - - return ret; -} diff --git a/contrib/wpa_supplicant/tests/test_sha256.c b/contrib/wpa_supplicant/tests/test_sha256.c deleted file mode 100644 index 161533ea7365..000000000000 --- a/contrib/wpa_supplicant/tests/test_sha256.c +++ /dev/null @@ -1,330 +0,0 @@ -/* - * Test program for SHA256 - * Copyright (c) 2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 { - char *data; - u8 hash[32]; -} tests[] = { - { - "abc", - { - 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, - 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, - 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, - 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad - } - }, - { - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - { - 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, - 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, - 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, - 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 - } - } -}; - -struct hmac_test { - u8 key[80]; - size_t key_len; - u8 data[128]; - size_t data_len; - u8 hash[32]; -} hmac_tests[] = { - /* draft-ietf-ipsec-ciph-sha-256-01.txt */ - { - { - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, - 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, - 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20 - }, - 32, - "abc", 3, - { - 0xa2, 0x1b, 0x1f, 0x5d, 0x4c, 0xf4, 0xf7, 0x3a, - 0x4d, 0xd9, 0x39, 0x75, 0x0f, 0x7a, 0x06, 0x6a, - 0x7f, 0x98, 0xcc, 0x13, 0x1c, 0xb1, 0x6a, 0x66, - 0x92, 0x75, 0x90, 0x21, 0xcf, 0xab, 0x81, 0x81 - } - }, - { - { - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, - 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, - 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20 - }, - 32, - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - 56, - { - 0x10, 0x4f, 0xdc, 0x12, 0x57, 0x32, 0x8f, 0x08, - 0x18, 0x4b, 0xa7, 0x31, 0x31, 0xc5, 0x3c, 0xae, - 0xe6, 0x98, 0xe3, 0x61, 0x19, 0x42, 0x11, 0x49, - 0xea, 0x8c, 0x71, 0x24, 0x56, 0x69, 0x7d, 0x30 - } - }, - { - { - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, - 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, - 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20 - }, - 32, - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - 112, - { - 0x47, 0x03, 0x05, 0xfc, 0x7e, 0x40, 0xfe, 0x34, - 0xd3, 0xee, 0xb3, 0xe7, 0x73, 0xd9, 0x5a, 0xab, - 0x73, 0xac, 0xf0, 0xfd, 0x06, 0x04, 0x47, 0xa5, - 0xeb, 0x45, 0x95, 0xbf, 0x33, 0xa9, 0xd1, 0xa3 - } - }, - { - { - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, - 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b - }, - 32, - "Hi There", - 8, - { - 0x19, 0x8a, 0x60, 0x7e, 0xb4, 0x4b, 0xfb, 0xc6, - 0x99, 0x03, 0xa0, 0xf1, 0xcf, 0x2b, 0xbd, 0xc5, - 0xba, 0x0a, 0xa3, 0xf3, 0xd9, 0xae, 0x3c, 0x1c, - 0x7a, 0x3b, 0x16, 0x96, 0xa0, 0xb6, 0x8c, 0xf7 - } - }, - { - "Jefe", - 4, - "what do ya want for nothing?", - 28, - { - 0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, - 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7, - 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83, - 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43 - } - }, - { - { - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa - }, - 32, - { - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd - }, - 50, - { - 0xcd, 0xcb, 0x12, 0x20, 0xd1, 0xec, 0xcc, 0xea, - 0x91, 0xe5, 0x3a, 0xba, 0x30, 0x92, 0xf9, 0x62, - 0xe5, 0x49, 0xfe, 0x6c, 0xe9, 0xed, 0x7f, 0xdc, - 0x43, 0x19, 0x1f, 0xbd, 0xe4, 0x5c, 0x30, 0xb0 - } - }, - { - { - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, - 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, - 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, - 0x21, 0x22, 0x23, 0x24, 0x25 - }, - 37, - { - 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, - 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, - 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, - 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, - 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, - 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, - 0xcd, 0xcd - }, - 50, - { - 0xd4, 0x63, 0x3c, 0x17, 0xf6, 0xfb, 0x8d, 0x74, - 0x4c, 0x66, 0xde, 0xe0, 0xf8, 0xf0, 0x74, 0x55, - 0x6e, 0xc4, 0xaf, 0x55, 0xef, 0x07, 0x99, 0x85, - 0x41, 0x46, 0x8e, 0xb4, 0x9b, 0xd2, 0xe9, 0x17 - } - }, - { - { - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c - }, - 32, - "Test With Truncation", - 20, - { - 0x75, 0x46, 0xaf, 0x01, 0x84, 0x1f, 0xc0, 0x9b, - 0x1a, 0xb9, 0xc3, 0x74, 0x9a, 0x5f, 0x1c, 0x17, - 0xd4, 0xf5, 0x89, 0x66, 0x8a, 0x58, 0x7b, 0x27, - 0x00, 0xa9, 0xc9, 0x7c, 0x11, 0x93, 0xcf, 0x42 - } - }, - { - { - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa - }, - 80, - "Test Using Larger Than Block-Size Key - Hash Key First", - 54, - { - 0x69, 0x53, 0x02, 0x5e, 0xd9, 0x6f, 0x0c, 0x09, - 0xf8, 0x0a, 0x96, 0xf7, 0x8e, 0x65, 0x38, 0xdb, - 0xe2, 0xe7, 0xb8, 0x20, 0xe3, 0xdd, 0x97, 0x0e, - 0x7d, 0xdd, 0x39, 0x09, 0x1b, 0x32, 0x35, 0x2f - } - }, - { - { - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa - }, - 80, - "Test Using Larger Than Block-Size Key and Larger Than One " - "Block-Size Data", - 73, - { - 0x63, 0x55, 0xac, 0x22, 0xe8, 0x90, 0xd0, 0xa3, - 0xc8, 0x48, 0x1a, 0x5c, 0xa4, 0x82, 0x5b, 0xc8, - 0x84, 0xd3, 0xe7, 0xa1, 0xff, 0x98, 0xa2, 0xfc, - 0x2a, 0xc7, 0xd8, 0xe0, 0x64, 0xc3, 0xb2, 0xe6 - } - } -}; - - -int main(int argc, char *argv[]) -{ - - unsigned int i; - u8 hash[32]; - const u8 *addr[2]; - size_t len[2]; - int errors = 0; - - for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { - printf("SHA256 test case %d:", i + 1); - - addr[0] = (u8 *) tests[i].data; - len[0] = strlen(tests[i].data); - sha256_vector(1, addr, len, hash); - if (memcmp(hash, tests[i].hash, 32) != 0) { - printf(" FAIL"); - errors++; - } else - printf(" OK"); - - if (len[0]) { - addr[0] = (u8 *) tests[i].data; - len[0] = 1; - addr[1] = (u8 *) tests[i].data + 1; - len[1] = strlen(tests[i].data) - 1; - sha256_vector(2, addr, len, hash); - if (memcmp(hash, tests[i].hash, 32) != 0) { - printf(" FAIL"); - errors++; - } else - printf(" OK"); - } - - printf("\n"); - } - - for (i = 0; i < sizeof(hmac_tests) / sizeof(hmac_tests[0]); i++) { - struct hmac_test *t = &hmac_tests[i]; - printf("HMAC-SHA256 test case %d:", i + 1); - - hmac_sha256(t->key, t->key_len, t->data, t->data_len, hash); - if (memcmp(hash, t->hash, 32) != 0) { - printf(" FAIL"); - errors++; - } else - printf(" OK"); - - addr[0] = t->data; - len[0] = t->data_len; - hmac_sha256_vector(t->key, t->key_len, 1, addr, len, hash); - if (memcmp(hash, t->hash, 32) != 0) { - printf(" FAIL"); - errors++; - } else - printf(" OK"); - - if (len[0]) { - addr[0] = t->data; - len[0] = 1; - addr[1] = t->data + 1; - len[1] = t->data_len - 1; - hmac_sha256_vector(t->key, t->key_len, 2, addr, len, - hash); - if (memcmp(hash, t->hash, 32) != 0) { - printf(" FAIL"); - errors++; - } else - printf(" OK"); - } - - printf("\n"); - } - - printf("Test IEEE 802.11r KDF\n"); - sha256_prf("abc", 3, "KDF test", "data", 4, hash, sizeof(hash)); - /* TODO: add proper test case for this */ - - return errors; -} diff --git a/contrib/wpa_supplicant/tests/test_x509v3.c b/contrib/wpa_supplicant/tests/test_x509v3.c deleted file mode 100644 index aa98ecedd76f..000000000000 --- a/contrib/wpa_supplicant/tests/test_x509v3.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Testing tool for X.509v3 routines - * Copyright (c) 2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "x509v3.h" - -extern int wpa_debug_level; - - -int main(int argc, char *argv[]) -{ - char *buf; - size_t len; - struct x509_certificate *certs = NULL, *last = NULL, *cert; - int i, reason; - - wpa_debug_level = 0; - - if (argc < 3 || strcmp(argv[1], "-v") != 0) { - printf("usage: test_x509v3 -v <cert1.der> <cert2.der> ..\n"); - return -1; - } - - for (i = 2; i < argc; i++) { - printf("Reading: %s\n", argv[i]); - buf = os_readfile(argv[i], &len); - if (buf == NULL) { - printf("Failed to read '%s'\n", argv[i]); - return -1; - } - - cert = x509_certificate_parse(buf, len); - if (cert == NULL) { - printf("Failed to parse X.509 certificate\n"); - return -1; - } - - free(buf); - - if (certs == NULL) - certs = cert; - else - last->next = cert; - last = cert; - } - - printf("\n\nValidating certificate chain\n"); - if (x509_certificate_chain_validate(last, certs, &reason) < 0) { - printf("\nCertificate chain validation failed: %d\n", reason); - return -1; - } - printf("\nCertificate chain is valid\n"); - - return 0; -} diff --git a/contrib/wpa_supplicant/tls.h b/contrib/wpa_supplicant/tls.h deleted file mode 100644 index 30d8842837fc..000000000000 --- a/contrib/wpa_supplicant/tls.h +++ /dev/null @@ -1,521 +0,0 @@ -/* - * WPA Supplicant / SSL/TLS interface definition - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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; -}; - -struct tls_config { - const char *opensc_engine_path; - const char *pkcs11_engine_path; - const char *pkcs11_module_path; -}; - -/** - * 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 key id (this is OpenSSL specific for now) - * @tls_ia: Whether to enable TLS/IA (for EAP-TTLSv1) - * - * 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; -}; - - -/** - * 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 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 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 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 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 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 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 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 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 - * - * Caller is responsible for freeing 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. 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. - */ -u8 * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len, u8 **appl_data, - size_t *appl_data_len); - -/** - * 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 - * @in_len: Input data length - * @out_len: Length of the output buffer. - * Returns: pointer to output data, %NULL on failure - * - * Caller is responsible for freeing returned output data. - */ -u8 * tls_connection_server_handshake(void *tls_ctx, - struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len); - -/** - * 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: 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 tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len); - -/** - * 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: 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 tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len); - -/** - * 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); - -/** - * tls_connection_set_master_key - Configure master secret for TLS connection - * @tls_ctx: TLS context data from tls_init() - * @conn: Connection context data from tls_connection_init() - * @key: TLS pre-master-secret - * @key_len: length of key in bytes - * Returns: 0 on success, -1 on failure - */ -int tls_connection_set_master_key(void *tls_ctx, struct tls_connection *conn, - const u8 *key, size_t key_len); - -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 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 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 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 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 - * @out_data: Pointer to output buffer (encrypted TLS/IA data) - * @out_len: Maximum out_data length - * Returns: Number of bytes written to out_data on success, -1 on failure - * - * This function is used to send the TLS/IA end phase message, e.g., when the - * EAP server completes EAP-TTLSv1. - */ -int tls_connection_ia_send_phase_finished(void *tls_ctx, - struct tls_connection *conn, - int final, - u8 *out_data, size_t out_len); - -/** - * 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 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 tls_connection_ia_permute_inner_secret(void *tls_ctx, - struct tls_connection *conn, - const u8 *key, size_t key_len); - -#endif /* TLS_H */ diff --git a/contrib/wpa_supplicant/tls_gnutls.c b/contrib/wpa_supplicant/tls_gnutls.c deleted file mode 100644 index 07893983189d..000000000000 --- a/contrib/wpa_supplicant/tls_gnutls.c +++ /dev/null @@ -1,1370 +0,0 @@ -/* - * WPA Supplicant / SSL/TLS interface functions for openssl - * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 <gnutls/gnutls.h> -#include <gnutls/x509.h> -#ifdef PKCS12_FUNCS -#include <gnutls/pkcs12.h> -#endif /* PKCS12_FUNCS */ - -#ifdef CONFIG_GNUTLS_EXTRA -#if LIBGNUTLS_VERSION_NUMBER >= 0x010302 -#define GNUTLS_IA -#include <gnutls/extra.h> -#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" - - -#define TLS_RANDOM_SIZE 32 -#define TLS_MASTER_SIZE 48 - - -#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; - - u8 *push_buf, *pull_buf, *pull_buf_offset; - size_t push_buf_len, pull_buf_len; - - 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; - u8 *end; - if (conn->pull_buf == NULL) { - errno = EWOULDBLOCK; - return -1; - } - - end = conn->pull_buf + conn->pull_buf_len; - 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__); - os_free(conn->pull_buf); - conn->pull_buf = conn->pull_buf_offset = NULL; - conn->pull_buf_len = 0; - } else { - wpa_printf(MSG_DEBUG, "%s - %d bytes remaining in pull_buf", - __func__, 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; - u8 *nbuf; - - nbuf = os_realloc(conn->push_buf, conn->push_buf_len + len); - if (nbuf == NULL) { - errno = ENOMEM; - return -1; - } - os_memcpy(nbuf + conn->push_buf_len, buf, len); - conn->push_buf = nbuf; - conn->push_buf_len += 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); - os_free(conn->push_buf); - os_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); - os_free(conn->push_buf); - conn->push_buf = NULL; - conn->push_buf_len = 0; - 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->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->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) -{ - 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"); - return -1; - } - - if (conn->verify_peer && (status & GNUTLS_CERT_INVALID)) { - wpa_printf(MSG_INFO, "TLS: Peer certificate not trusted"); - return -1; - } - - if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) { - wpa_printf(MSG_INFO, "TLS: Peer certificate does not have a " - "known issuer"); - return -1; - } - - if (status & GNUTLS_CERT_REVOKED) { - wpa_printf(MSG_INFO, "TLS: Peer certificate has been 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"); - 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"); - 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); - 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); - return -1; - } - - gnutls_x509_crt_deinit(cert); - } - - return 0; -} - - -u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len, u8 **appl_data, - size_t *appl_data_len) -{ - struct tls_global *global = ssl_ctx; - u8 *out_data; - int ret; - - if (appl_data) - *appl_data = NULL; - - if (in_data && in_len) { - if (conn->pull_buf) { - wpa_printf(MSG_DEBUG, "%s - %d bytes remaining in " - "pull_buf", __func__, conn->pull_buf_len); - os_free(conn->pull_buf); - } - conn->pull_buf = os_malloc(in_len); - if (conn->pull_buf == NULL) - return NULL; - os_memcpy(conn->pull_buf, in_data, in_len); - conn->pull_buf_offset = conn->pull_buf; - conn->pull_buf_len = in_len; - } - - 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 = os_malloc(1); - } - 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; - - if (conn->verify_peer && tls_connection_verify_peer(conn)) { - wpa_printf(MSG_INFO, "TLS: Peer certificate chain " - "failed validation"); - conn->failed++; - return NULL; - } - - if (conn->tls_ia && !gnutls_ia_handshake_p(conn->session)) { - wpa_printf(MSG_INFO, "TLS: No TLS/IA negotiation"); - conn->failed++; - return NULL; - } - - 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 = os_malloc(1); - } - - 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); - } - } - - out_data = conn->push_buf; - *out_len = conn->push_buf_len; - conn->push_buf = NULL; - conn->push_buf_len = 0; - return out_data; -} - - -u8 * tls_connection_server_handshake(void *ssl_ctx, - struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len) -{ - return tls_connection_handshake(ssl_ctx, conn, in_data, in_len, - out_len, NULL, NULL); -} - - -int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ - ssize_t res; - -#ifdef GNUTLS_IA - if (conn->tls_ia) - res = gnutls_ia_send(conn->session, (char *) in_data, in_len); - else -#endif /* GNUTLS_IA */ - res = gnutls_record_send(conn->session, in_data, in_len); - if (res < 0) { - wpa_printf(MSG_INFO, "%s: Encryption failed: %s", - __func__, gnutls_strerror(res)); - return -1; - } - if (conn->push_buf == NULL) - return -1; - if (conn->push_buf_len < out_len) - out_len = conn->push_buf_len; - os_memcpy(out_data, conn->push_buf, out_len); - os_free(conn->push_buf); - conn->push_buf = NULL; - conn->push_buf_len = 0; - return out_len; -} - - -int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ - ssize_t res; - - if (conn->pull_buf) { - wpa_printf(MSG_DEBUG, "%s - %d bytes remaining in " - "pull_buf", __func__, conn->pull_buf_len); - os_free(conn->pull_buf); - } - conn->pull_buf = os_malloc(in_len); - if (conn->pull_buf == NULL) - return -1; - os_memcpy(conn->pull_buf, in_data, in_len); - conn->pull_buf_offset = conn->pull_buf; - conn->pull_buf_len = in_len; - -#ifdef GNUTLS_IA - if (conn->tls_ia) { - res = gnutls_ia_recv(conn->session, (char *) out_data, - out_len); - if (out_len >= 12 && - (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)); - return -1; - } - - res = gnutls_ia_verify_endphase(conn->session, - (char *) out_data); - 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)); - return -1; - } - - if (final) - conn->final_phase_finished = 1; - - return 0; - } - - if (res < 0) { - wpa_printf(MSG_DEBUG, "%s - gnutls_ia_recv failed: %d " - "(%s)", __func__, res, - gnutls_strerror(res)); - } - return res; - } -#endif /* GNUTLS_IA */ - - res = gnutls_record_recv(conn->session, out_data, out_len); - if (res < 0) { - wpa_printf(MSG_DEBUG, "%s - gnutls_record_recv failed: %d " - "(%s)", __func__, res, gnutls_strerror(res)); - } - - return res; -} - - -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_master_key(void *ssl_ctx, struct tls_connection *conn, - const u8 *key, size_t key_len) -{ - /* TODO */ - return -1; -} - - -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) -{ - /* TODO: set SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS */ - 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 */ -} - - -int tls_connection_ia_send_phase_finished(void *tls_ctx, - struct tls_connection *conn, - int final, - u8 *out_data, size_t out_len) -{ -#ifdef GNUTLS_IA - int ret; - - if (conn == NULL || conn->session == NULL || !conn->tls_ia) - return -1; - - 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 -1; - } - - 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 -1; - } - - if (conn->push_buf == NULL) - return -1; - if (conn->push_buf_len < out_len) - out_len = conn->push_buf_len; - os_memcpy(out_data, conn->push_buf, out_len); - os_free(conn->push_buf); - conn->push_buf = NULL; - conn->push_buf_len = 0; - return out_len; -#else /* GNUTLS_IA */ - return -1; -#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 */ -} diff --git a/contrib/wpa_supplicant/tls_internal.c b/contrib/wpa_supplicant/tls_internal.c deleted file mode 100644 index a3858dd8a9c7..000000000000 --- a/contrib/wpa_supplicant/tls_internal.c +++ /dev/null @@ -1,326 +0,0 @@ -/* - * WPA Supplicant / TLS interface functions and an internal TLS implementation - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "tlsv1_client.h" - - -static int tls_ref_count = 0; - -struct tls_global { - int dummy; -}; - -struct tls_connection { - struct tlsv1_client *client; -}; - - -void * tls_init(const struct tls_config *conf) -{ - struct tls_global *global; - - if (tls_ref_count == 0) { - if (tlsv1_client_global_init()) - return NULL; - } - 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) { - tlsv1_client_global_deinit(); - } - 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; - - conn = os_zalloc(sizeof(*conn)); - if (conn == NULL) - return NULL; - - conn->client = tlsv1_client_init(); - if (conn->client == NULL) { - os_free(conn); - return NULL; - } - - return conn; -} - - -void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn) -{ - if (conn == NULL) - return; - tlsv1_client_deinit(conn->client); - os_free(conn); -} - - -int tls_connection_established(void *tls_ctx, struct tls_connection *conn) -{ - return tlsv1_client_established(conn->client); -} - - -int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn) -{ - return tlsv1_client_shutdown(conn->client); -} - - -int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, - const struct tls_connection_params *params) -{ - if (tlsv1_client_set_ca_cert(conn->client, 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_client_set_client_cert(conn->client, params->client_cert, - params->client_cert_blob, - params->client_cert_blob_len)) { - wpa_printf(MSG_INFO, "TLS: Failed to configure client " - "certificate"); - return -1; - } - - if (tlsv1_client_set_private_key(conn->client, - 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; - } - - return 0; -} - - -int tls_global_set_params(void *tls_ctx, - const struct tls_connection_params *params) -{ - wpa_printf(MSG_INFO, "TLS: not implemented - %s", __func__); - return -1; -} - - -int tls_global_set_verify(void *tls_ctx, int check_crl) -{ - wpa_printf(MSG_INFO, "TLS: not implemented - %s", __func__); - 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 tlsv1_client_get_keys(conn->client, keys); -} - - -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 tlsv1_client_prf(conn->client, label, server_random_first, - out, out_len); -} - - -u8 * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len, u8 **appl_data, - size_t *appl_data_len) -{ - if (appl_data) - *appl_data = NULL; - - wpa_printf(MSG_DEBUG, "TLS: %s(in_data=%p in_len=%lu)", - __func__, in_data, (unsigned long) in_len); - return tlsv1_client_handshake(conn->client, in_data, in_len, out_len); -} - - -u8 * tls_connection_server_handshake(void *tls_ctx, - struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len) -{ - wpa_printf(MSG_INFO, "TLS: not implemented - %s", __func__); - return NULL; -} - - -int tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ - return tlsv1_client_encrypt(conn->client, in_data, in_len, out_data, - out_len); -} - - -int tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ - return tlsv1_client_decrypt(conn->client, in_data, in_len, out_data, - out_len); -} - - -int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn) -{ - return tlsv1_client_resumed(conn->client); -} - - -int tls_connection_set_master_key(void *tls_ctx, struct tls_connection *conn, - const u8 *key, size_t key_len) -{ - return tlsv1_client_set_master_key(conn->client, key, key_len); -} - - -int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, - u8 *ciphers) -{ - return tlsv1_client_set_cipher_list(conn->client, ciphers); -} - - -int tls_get_cipher(void *tls_ctx, struct tls_connection *conn, - char *buf, size_t buflen) -{ - if (conn == NULL) - return -1; - return tlsv1_client_get_cipher(conn->client, buf, buflen); -} - - -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 tlsv1_client_hello_ext(conn->client, ext_type, data, data_len); -} - - -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 tlsv1_client_get_keyblock_size(conn->client); -} - - -unsigned int tls_capabilities(void *tls_ctx) -{ - return 0; -} - - -int tls_connection_ia_send_phase_finished(void *tls_ctx, - struct tls_connection *conn, - int final, - u8 *out_data, size_t out_len) -{ - return -1; -} - - -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/contrib/wpa_supplicant/tls_none.c b/contrib/wpa_supplicant/tls_none.c deleted file mode 100644 index ad08d5076c88..000000000000 --- a/contrib/wpa_supplicant/tls_none.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * WPA Supplicant / SSL/TLS interface functions for no TLS case - * Copyright (c) 2004, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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) -{ -} - - -#ifdef EAP_TLS_NONE - -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; -} - - -u8 * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len, u8 **appl_data, - size_t *appl_data_len) -{ - return NULL; -} - - -u8 * tls_connection_server_handshake(void *tls_ctx, - struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len) -{ - return NULL; -} - - -int tls_connection_encrypt(void *tls_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ - return -1; -} - - -int tls_connection_decrypt(void *tls_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ - return -1; -} - - -int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn) -{ - return 0; -} - - -int tls_connection_set_master_key(void *tls_ctx, struct tls_connection *conn, - const u8 *key, size_t key_len) -{ - return -1; -} - - -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; -} - - -int tls_connection_ia_send_phase_finished(void *tls_ctx, - struct tls_connection *conn, - int final, - u8 *out_data, size_t out_len) -{ - return -1; -} - - -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; -} - -#endif /* EAP_TLS_NONE */ diff --git a/contrib/wpa_supplicant/tls_openssl.c b/contrib/wpa_supplicant/tls_openssl.c deleted file mode 100644 index cb6b97434e46..000000000000 --- a/contrib/wpa_supplicant/tls_openssl.c +++ /dev/null @@ -1,2337 +0,0 @@ -/* - * WPA Supplicant / SSL/TLS interface functions for openssl - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 <openssl/ssl.h> -#include <openssl/err.h> -#include <openssl/pkcs12.h> -#include <openssl/x509v3.h> -#ifndef OPENSSL_NO_ENGINE -#include <openssl/engine.h> -#endif /* OPENSSL_NO_ENGINE */ - -#include "common.h" -#include "tls.h" - -#if OPENSSL_VERSION_NUMBER >= 0x0090800fL -#define OPENSSL_d2i_TYPE const unsigned char ** -#else -#define OPENSSL_d2i_TYPE unsigned char ** -#endif - -static int tls_openssl_ref_count = 0; - -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; - - u8 *pre_shared_secret; - size_t pre_shared_secret_len; -}; - - -#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 <wincrypt.h> - -#ifdef __MINGW32_VERSION -/* - * MinGW does not yet include all the needed definitions for CryptoAPI, so - * define here whatever extra is needed. - */ -#define CALG_SSL3_SHAMD5 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SSL3SHAMD5) -#define CERT_SYSTEM_STORE_CURRENT_USER (1 << 16) -#define CERT_STORE_READONLY_FLAG 0x00008000 -#define CERT_STORE_OPEN_EXISTING_FLAG 0x00004000 -#define CRYPT_ACQUIRE_COMPARE_KEY_FLAG 0x00000004 - -static BOOL WINAPI -(*CryptAcquireCertificatePrivateKey)(PCCERT_CONTEXT pCert, DWORD dwFlags, - void *pvReserved, HCRYPTPROV *phCryptProv, - DWORD *pdwKeySpec, BOOL *pfCallerFreeProv) -= NULL; /* to be loaded from crypt32.dll */ - -static PCCERT_CONTEXT WINAPI -(*CertEnumCertificatesInStore)(HCERTSTORE hCertStore, - PCCERT_CONTEXT pPrevCertContext) -= 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 (CryptAcquireCertificatePrivateKey) - return 0; - - dll = LoadLibrary("crypt32"); - if (dll == NULL) { - wpa_printf(MSG_DEBUG, "CryptoAPI: Could not load crypt32 " - "library"); - return -1; - } - - CryptAcquireCertificatePrivateKey = GetProcAddress( - dll, "CryptAcquireCertificatePrivateKey"); - if (CryptAcquireCertificatePrivateKey == NULL) { - wpa_printf(MSG_DEBUG, "CryptoAPI: Could not get " - "CryptAcquireCertificatePrivateKey() address from " - "crypt32 library"); - return -1; - } - - CertEnumCertificatesInStore = (void *) GetProcAddress( - dll, "CertEnumCertificatesInStore"); - if (CertEnumCertificatesInStore == NULL) { - wpa_printf(MSG_DEBUG, "CryptoAPI: Could not get " - "CertEnumCertificatesInStore() address from " - "crypt32 library"); - return -1; - } - - return 0; -} - -#else /* __MINGW32_VERSION */ - -static int mingw_load_crypto_func(void) -{ - return 0; -} - -#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 (mingw_load_crypto_func()) - 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 (mingw_load_crypto_func()) - return -1; - - 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) { - SSL_load_error_strings(); - SSL_library_init(); - /* 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 - 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 */ - ERR_free_strings(); - EVP_cleanup(); - } -} - - -static int tls_engine_init(struct tls_connection *conn, const char *engine_id, - const char *pin, const char *key_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; - } - 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; - } - 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; - os_free(conn->pre_shared_secret); - SSL_free(conn->ssl); - tls_engine_deinit(conn); - os_free(conn->subject_match); - os_free(conn->altsubject_match); - 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 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 && os_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; -} - - -#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 */ - - -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; - } - - 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__); - SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb); - return 0; - } - -#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"); - SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb); - 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); - } - SSL_set_verify(conn->ssl, SSL_VERIFY_PEER, tls_verify_cb); -#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 */ - SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL); - } - - 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) -{ - if (conn == NULL) - return -1; - - if (verify_peer) { - SSL_set_verify(conn->ssl, SSL_VERIFY_PEER | - SSL_VERIFY_FAIL_IF_NO_PEER_CERT | - SSL_VERIFY_CLIENT_ONCE, tls_verify_cb); - } else { - SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL); - } - - SSL_set_accept_state(conn->ssl); - - 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; - -#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; - } else { - tls_show_errors(MSG_DEBUG, __func__, - "SSL_use_certificate_file (DER) failed"); - } - - if (SSL_use_certificate_file(conn->ssl, client_cert, - SSL_FILETYPE_PEM) == 1) { - wpa_printf(MSG_DEBUG, "OpenSSL: SSL_use_certificate_file (PEM)" - " --> OK"); - return 0; - } else { - tls_show_errors(MSG_DEBUG, __func__, - "SSL_use_certificate_file (PEM) 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_strncpy(buf, (char *) password, size); - buf[size - 1] = '\0'; - 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 */ -} - - -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; - } else { - tls_show_errors(MSG_DEBUG, __func__, - "SSL_use_PrivateKey_ASN1(EVP_PKEY_RSA)" - " failed"); - } - - 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; - } else { - tls_show_errors(MSG_DEBUG, __func__, - "SSL_use_PrivateKey_ASN1(EVP_PKEY_DSA)" - " failed"); - } - - 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; - } else { - tls_show_errors(MSG_DEBUG, __func__, - "SSL_use_RSAPrivateKey_ASN1 failed"); - } - - 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; - } - - 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; - } else { - tls_show_errors(MSG_DEBUG, __func__, - "SSL_use_PrivateKey_File (DER) " - "failed"); - } - - 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 { - tls_show_errors(MSG_DEBUG, __func__, - "SSL_use_PrivateKey_File (PEM) " - "failed"); - } -#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) { - wpa_printf(MSG_INFO, "OpenSSL: Failed to load private key"); - os_free(passwd); - ERR_clear_error(); - 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 */ -} - - -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; -} - - -u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len, u8 **appl_data, - size_t *appl_data_len) -{ - int res; - u8 *out_data; - - if (appl_data) - *appl_data = NULL; - - /* - * Give TLS handshake data from the server (if available) to OpenSSL - * for processing. - */ - if (in_data && - BIO_write(conn->ssl_in, in_data, in_len) < 0) { - tls_show_errors(MSG_INFO, __func__, - "Handshake failed - BIO_write"); - return NULL; - } - - /* Initiate TLS handshake or continue the existing handshake */ - 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 = os_malloc(res == 0 ? 1 : 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"); - } - *out_len = 0; - return NULL; - } - res = res == 0 ? 0 : BIO_read(conn->ssl_out, 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"); - } - *out_len = 0; - return NULL; - } - *out_len = res; - - if (SSL_is_init_finished(conn->ssl) && appl_data) { - *appl_data = os_malloc(in_len); - if (*appl_data) { - res = SSL_read(conn->ssl, *appl_data, in_len); - if (res < 0) { - tls_show_errors(MSG_INFO, __func__, - "Failed to read possible " - "Application Data"); - os_free(*appl_data); - *appl_data = NULL; - } else { - *appl_data_len = res; - wpa_hexdump_key(MSG_MSGDUMP, "SSL: Application" - " Data in Finish message", - *appl_data, *appl_data_len); - } - } - } - - return out_data; -} - - -u8 * tls_connection_server_handshake(void *ssl_ctx, - struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len) -{ - int res; - u8 *out_data; - char buf[10]; - - if (in_data && - BIO_write(conn->ssl_in, in_data, in_len) < 0) { - tls_show_errors(MSG_INFO, __func__, - "Handshake failed - BIO_write"); - return NULL; - } - - res = SSL_read(conn->ssl, buf, sizeof(buf)); - if (res >= 0) { - wpa_printf(MSG_DEBUG, "SSL: Unexpected data from SSL_read " - "(res=%d)", res); - } - - res = BIO_ctrl_pending(conn->ssl_out); - wpa_printf(MSG_DEBUG, "SSL: %d bytes pending from ssl_out", res); - out_data = os_malloc(res == 0 ? 1 : 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"); - } - *out_len = 0; - return NULL; - } - res = res == 0 ? 0 : BIO_read(conn->ssl_out, 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"); - } - *out_len = 0; - return NULL; - } - *out_len = res; - return out_data; -} - - -int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ - int res; - - if (conn == NULL) - return -1; - - /* 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 res; - } - res = SSL_write(conn->ssl, in_data, in_len); - if (res < 0) { - tls_show_errors(MSG_INFO, __func__, - "Encryption failed - SSL_write"); - return res; - } - - /* Read encrypted data to be sent to the server */ - res = BIO_read(conn->ssl_out, out_data, out_len); - if (res < 0) { - tls_show_errors(MSG_INFO, __func__, - "Encryption failed - BIO_read"); - return res; - } - - return res; -} - - -int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ - int res; - - /* Give encrypted data from TLS tunnel for OpenSSL to decrypt. */ - res = BIO_write(conn->ssl_in, in_data, in_len); - if (res < 0) { - tls_show_errors(MSG_INFO, __func__, - "Decryption failed - BIO_write"); - return res; - } - if (BIO_reset(conn->ssl_out) < 0) { - tls_show_errors(MSG_INFO, __func__, "BIO_reset failed"); - return res; - } - - /* Read decrypted data for further processing */ - res = SSL_read(conn->ssl, out_data, out_len); - if (res < 0) { - tls_show_errors(MSG_INFO, __func__, - "Decryption failed - SSL_read"); - return res; - } - - return res; -} - - -int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn) -{ - return conn ? conn->ssl->hit : 0; -} - - -#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) -/* 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; - - if (conn == NULL || conn->pre_shared_secret == 0) - return 0; - - os_memcpy(secret, conn->pre_shared_secret, - conn->pre_shared_secret_len); - *secret_len = conn->pre_shared_secret_len; - - return 1; -} - - -int tls_connection_set_master_key(void *ssl_ctx, struct tls_connection *conn, - const u8 *key, size_t key_len) -{ - if (conn == NULL || key_len > SSL_MAX_MASTER_KEY_LENGTH) - return -1; - - os_free(conn->pre_shared_secret); - conn->pre_shared_secret = NULL; - conn->pre_shared_secret_len = 0; - - if (key) { - conn->pre_shared_secret = os_malloc(key_len); - if (conn->pre_shared_secret) { - os_memcpy(conn->pre_shared_secret, key, key_len); - conn->pre_shared_secret_len = key_len; - } - if (SSL_set_session_secret_cb(conn->ssl, tls_sess_sec_cb, - conn) != 1) - return -1; - } else { - if (SSL_set_session_secret_cb(conn->ssl, NULL, NULL) != 1) - return -1; - } - - return 0; -} -#endif /* EAP_FAST || EAP_FAST_DYNAMIC */ - - -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_snprintf(buf, buflen, "%s", name); - buf[buflen - 1] = '\0'; - 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) -/* 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) - return -1; - - if (SSL_set_hello_extension(conn->ssl, ext_type, (void *) data, - data_len) != 1) - return -1; - - return 0; -} -#endif /* EAP_FAST || EAP_FAST_DYNAMIC */ - - -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 (tls_connection_set_subject_match(conn, - params->subject_match, - params->altsubject_match)) - return -1; - 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 (tls_connection_client_cert(conn, params->client_cert, - params->client_cert_blob, - params->client_cert_blob_len)) - return -1; - - if (params->engine) { - wpa_printf(MSG_DEBUG, "SSL: Initializing TLS engine"); - ret = tls_engine_init(conn, params->engine_id, params->pin, - params->key_id); - if (ret) - return ret; - 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; - - 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; -} - - -int tls_connection_ia_send_phase_finished(void *tls_ctx, - struct tls_connection *conn, - int final, - u8 *out_data, size_t out_len) -{ - return -1; -} - - -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/contrib/wpa_supplicant/tls_schannel.c b/contrib/wpa_supplicant/tls_schannel.c deleted file mode 100644 index 4ecfae0063fb..000000000000 --- a/contrib/wpa_supplicant/tls_schannel.c +++ /dev/null @@ -1,796 +0,0 @@ -/* - * WPA Supplicant / SSL/TLS interface functions for Microsoft Schannel - * Copyright (c) 2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 <windows.h> -#include <wincrypt.h> -#include <schannel.h> -#define SECURITY_WIN32 -#include <security.h> -#include <sspi.h> - -#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 u8 * tls_conn_hs_clienthello(struct tls_global *global, - struct tls_connection *conn, - size_t *out_len) -{ - 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) { - u8 *buf; - wpa_hexdump(MSG_MSGDUMP, "SChannel - ClientHello", - outbufs[0].pvBuffer, outbufs[0].cbBuffer); - conn->start = 0; - *out_len = outbufs[0].cbBuffer; - buf = os_malloc(*out_len); - if (buf == NULL) - return NULL; - os_memcpy(buf, outbufs[0].pvBuffer, *out_len); - 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; -} - - -u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len, u8 **appl_data, - size_t *appl_data_len) -{ - struct tls_global *global = ssl_ctx; - DWORD sspi_flags, sspi_flags_out; - SecBufferDesc inbuf, outbuf; - SecBuffer inbufs[2], outbufs[1]; - SECURITY_STATUS status; - TimeStamp ts_expiry; - u8 *out_buf = NULL; - - if (appl_data) - *appl_data = NULL; - - if (conn->start) { - return tls_conn_hs_clienthello(global, conn, out_len); - } - - wpa_printf(MSG_DEBUG, "SChannel: %d bytes handshake data to process", - in_len); - - 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 *) in_data; - inbufs[0].cbBuffer = in_len; - 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_len = outbufs[0].cbBuffer; - out_buf = os_malloc(*out_len); - if (out_buf) - os_memcpy(out_buf, outbufs[0].pvBuffer, - *out_len); - 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 = os_malloc(1); - - 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_len = outbufs[1].cbBuffer; - appl_data = os_malloc(*appl_data_len); - if (appl_data) - os_memcpy(appl_data, - outbufs[1].pvBuffer, - *appl_data_len); - } - 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; -} - - -u8 * tls_connection_server_handshake(void *ssl_ctx, - struct tls_connection *conn, - const u8 *in_data, size_t in_len, - size_t *out_len) -{ - return NULL; -} - - -int tls_connection_encrypt(void *ssl_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ - struct tls_global *global = ssl_ctx; - SECURITY_STATUS status; - SecBufferDesc buf; - SecBuffer bufs[4]; - SecPkgContext_StreamSizes sizes; - int i; - size_t total_len; - - 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 -1; - } - wpa_printf(MSG_DEBUG, "%s: Stream sizes: header=%u trailer=%u", - __func__, - (unsigned int) sizes.cbHeader, - (unsigned int) sizes.cbTrailer); - - total_len = sizes.cbHeader + in_len + sizes.cbTrailer; - - if (out_len < total_len) { - wpa_printf(MSG_DEBUG, "%s: too short out_data (out_len=%lu " - "in_len=%lu total_len=%lu)", __func__, - (unsigned long) out_len, (unsigned long) in_len, - (unsigned long) total_len); - return -1; - } - - os_memset(&bufs, 0, sizeof(bufs)); - bufs[0].pvBuffer = out_data; - bufs[0].cbBuffer = sizes.cbHeader; - bufs[0].BufferType = SECBUFFER_STREAM_HEADER; - - os_memcpy(out_data + sizes.cbHeader, in_data, in_len); - bufs[1].pvBuffer = out_data + sizes.cbHeader; - bufs[1].cbBuffer = in_len; - bufs[1].BufferType = SECBUFFER_DATA; - - bufs[2].pvBuffer = out_data + sizes.cbHeader + in_len; - 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", - out_data, 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_key(MSG_MSGDUMP, "Schannel: Encrypted data from " - "EncryptMessage", out_data, total_len); - return total_len; - } - - wpa_printf(MSG_DEBUG, "%s: Failed - status=%d", - __func__, (int) status); - return -1; -} - - -int tls_connection_decrypt(void *ssl_ctx, struct tls_connection *conn, - const u8 *in_data, size_t in_len, - u8 *out_data, size_t out_len) -{ - struct tls_global *global = ssl_ctx; - SECURITY_STATUS status; - SecBufferDesc buf; - SecBuffer bufs[4]; - int i; - - if (out_len < in_len) { - wpa_printf(MSG_DEBUG, "%s: out_len=%lu < in_len=%lu", __func__, - (unsigned long) out_len, (unsigned long) in_len); - return -1; - } - - wpa_hexdump(MSG_MSGDUMP, "Schannel: Encrypted data to DecryptMessage", - in_data, in_len); - os_memset(&bufs, 0, sizeof(bufs)); - os_memcpy(out_data, in_data, in_len); - bufs[0].pvBuffer = out_data; - bufs[0].cbBuffer = in_len; - 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", - out_data, 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__); - return -1; - } - wpa_hexdump_key(MSG_MSGDUMP, "Schannel: Decrypted data from " - "DecryptMessage", - bufs[i].pvBuffer, bufs[i].cbBuffer); - if (bufs[i].cbBuffer > out_len) { - wpa_printf(MSG_DEBUG, "%s: Too long output data", - __func__); - return -1; - } - os_memmove(out_data, bufs[i].pvBuffer, bufs[i].cbBuffer); - return bufs[i].cbBuffer; - } - - wpa_printf(MSG_DEBUG, "%s: Failed - status=%d", - __func__, (int) status); - return -1; -} - - -int tls_connection_resumed(void *ssl_ctx, struct tls_connection *conn) -{ - return 0; -} - - -int tls_connection_set_master_key(void *ssl_ctx, struct tls_connection *conn, - const u8 *key, size_t key_len) -{ - return -1; -} - - -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; -} - - -int tls_connection_ia_send_phase_finished(void *tls_ctx, - struct tls_connection *conn, - int final, - u8 *out_data, size_t out_len) -{ - return -1; -} - - -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/contrib/wpa_supplicant/tlsv1_client.c b/contrib/wpa_supplicant/tlsv1_client.c deleted file mode 100644 index 2d62ff0ab60c..000000000000 --- a/contrib/wpa_supplicant/tlsv1_client.c +++ /dev/null @@ -1,2609 +0,0 @@ -/* - * wpa_supplicant: TLSv1 client (RFC 2246) - * Copyright (c) 2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "md5.h" -#include "sha1.h" -#include "crypto.h" -#include "tls.h" -#include "tlsv1_common.h" -#include "tlsv1_client.h" -#include "x509v3.h" - -/* TODO: - * Support for a message fragmented across several records (RFC 2246, 6.2.1) - */ - -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 ticket:1; - unsigned int ticket_key:1; - - struct crypto_public_key *server_rsa_key; - - struct crypto_hash *verify_md5_client; - struct crypto_hash *verify_sha1_client; - struct crypto_hash *verify_md5_server; - struct crypto_hash *verify_sha1_server; - struct crypto_hash *verify_md5_cert; - struct crypto_hash *verify_sha1_cert; - -#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 x509_certificate *trusted_certs; - struct x509_certificate *client_cert; - struct crypto_private_key *client_key; -}; - - -static int tls_derive_keys(struct tlsv1_client *conn, - const u8 *pre_master_secret, - size_t pre_master_secret_len); -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 void tls_alert(struct tlsv1_client *conn, u8 level, u8 description) -{ - conn->alert_level = level; - conn->alert_description = description; -} - - -static void tls_verify_hash_add(struct tlsv1_client *conn, const u8 *buf, - size_t len) -{ - if (conn->verify_md5_client && conn->verify_sha1_client) { - crypto_hash_update(conn->verify_md5_client, buf, len); - crypto_hash_update(conn->verify_sha1_client, buf, len); - } - if (conn->verify_md5_server && conn->verify_sha1_server) { - crypto_hash_update(conn->verify_md5_server, buf, len); - crypto_hash_update(conn->verify_sha1_server, buf, len); - } - if (conn->verify_md5_cert && conn->verify_sha1_cert) { - crypto_hash_update(conn->verify_md5_cert, buf, len); - crypto_hash_update(conn->verify_sha1_cert, buf, len); - } -} - - -static u8 * tls_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; -} - - -static 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 (os_get_random(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, 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_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; - - if (conn->session_resumed || conn->ticket_key) - tls_derive_keys(conn, NULL, 0); - - /* 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) { - wpa_hexdump(MSG_DEBUG, "TLSv1: Unexpected extra data in the " - "end of ServerHello", pos, end - pos); - goto decode_error; - } - - *in_len = end - in_data; - - conn->state = (conn->session_resumed || conn->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_server_key_exchange_allowed(struct tlsv1_client *conn) -{ - const struct tls_cipher_suite *suite; - - /* RFC 2246, Section 7.4.3 */ - suite = tls_get_cipher_suite(conn->rl.cipher_suite); - 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; - } -} - - -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 (x509_certificate_chain_validate(conn->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 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; -} - - -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) - 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: - 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)) { - 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); - 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->ticket) ? - CHANGE_CIPHER_SPEC : ACK_FINISHED; - - return 0; -} - - -static 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; -} - - -static 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; -} - - -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->client_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)); - 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->trusted_certs, - &cert->issuer); - } - if (cert == conn->client_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, hs_start, pos - hs_start); - - *msgpos = pos; - - return 0; -} - - -static int tlsv1_key_x_anon_dh(struct tlsv1_client *conn, u8 **pos, u8 *end) -{ -#ifdef EAP_FAST - /* 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 (os_get_random(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; - } - 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); - - 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 */ - crypto_mod_exp(conn->dh_ys, conn->dh_ys_len, - csecret_start, csecret_len, - conn->dh_p, conn->dh_p_len, - shared, &shared_len); - 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; -#else /* EAP_FAST */ - tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); - return -1; -#endif /* EAP_FAST */ -} - - -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, 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 (crypto_private_key_sign_pkcs1(conn->client_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, 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, 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 size_t tls_client_cert_chain_der_len(struct tlsv1_client *conn) -{ - size_t len = 0; - struct x509_certificate *cert; - - cert = conn->client_cert; - while (cert) { - len += 3 + cert->cert_len; - if (x509_certificate_self_signed(cert)) - break; - cert = x509_certificate_get_subject(conn->trusted_certs, - &cert->issuer); - } - - return len; -} - - -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 = 1000; - 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->client_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; -} - - -static int tlsv1_client_process_handshake(struct tlsv1_client *conn, u8 ct, - const u8 *buf, size_t *len) -{ - 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; - 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, buf, *len); - - 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. - * 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) -{ - const u8 *pos, *end; - u8 *msg = NULL, *in_msg, *in_pos, *in_end, alert, ct; - size_t in_msg_len; - - 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) < 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; - - switch (conn->state) { - case CLIENT_KEY_EXCHANGE: - msg = tls_send_client_key_exchange(conn, out_len); - break; - case CHANGE_CIPHER_SPEC: - msg = tls_send_change_cipher_spec(conn, out_len); - break; - case ACK_FINISHED: - wpa_printf(MSG_DEBUG, "TLSv1: Handshake completed " - "successfully"); - conn->state = ESTABLISHED; - /* Need to return something to get final TLS ACK. */ - msg = os_malloc(1); - *out_len = 0; - break; - default: - wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d while " - "generating reply", conn->state); - break; - } - -failed: - os_free(in_msg); - if (conn->alert_level) { - conn->state = FAILED; - os_free(msg); - msg = tls_send_alert(conn, conn->alert_level, - conn->alert_description, out_len); - } - - 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(); -} - - -static void tlsv1_client_free_verify_hashes(struct tlsv1_client *conn) -{ - crypto_hash_finish(conn->verify_md5_client, NULL, NULL); - crypto_hash_finish(conn->verify_md5_server, NULL, NULL); - crypto_hash_finish(conn->verify_md5_cert, NULL, NULL); - crypto_hash_finish(conn->verify_sha1_client, NULL, NULL); - crypto_hash_finish(conn->verify_sha1_server, NULL, NULL); - crypto_hash_finish(conn->verify_sha1_cert, NULL, NULL); - conn->verify_md5_client = NULL; - conn->verify_md5_server = NULL; - conn->verify_md5_cert = NULL; - conn->verify_sha1_client = NULL; - conn->verify_sha1_server = NULL; - conn->verify_sha1_cert = NULL; -} - - -static int tlsv1_client_init_verify_hashes(struct tlsv1_client *conn) -{ - conn->verify_md5_client = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, - 0); - conn->verify_md5_server = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, - 0); - conn->verify_md5_cert = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0); - conn->verify_sha1_client = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, - 0); - conn->verify_sha1_server = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, - 0); - conn->verify_sha1_cert = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, - 0); - if (conn->verify_md5_client == NULL || - conn->verify_md5_server == NULL || - conn->verify_md5_cert == NULL || - conn->verify_sha1_client == NULL || - conn->verify_sha1_server == NULL || - conn->verify_sha1_cert == NULL) { - tlsv1_client_free_verify_hashes(conn); - return -1; - } - return 0; -} - - -/** - * 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 (tlsv1_client_init_verify_hashes(conn) < 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); - tlsv1_client_free_verify_hashes(conn); - os_free(conn->client_hello_ext); - tlsv1_client_free_dh(conn); - x509_certificate_chain_free(conn->trusted_certs); - x509_certificate_chain_free(conn->client_cert); - crypto_private_key_free(conn->client_key); - 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; - default: - return -1; - } - - os_snprintf(buf, buflen, "%s", cipher); - 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; - - tlsv1_client_free_verify_hashes(conn); - if (tlsv1_client_init_verify_hashes(conn) < 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->ticket = 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->ticket = 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_set_master_key - Configure master secret for TLS connection - * @conn: TLSv1 client connection data from tlsv1_client_init() - * @key: TLS pre-master-secret - * @key_len: length of key in bytes - * Returns: 0 on success, -1 on failure - */ -int tlsv1_client_set_master_key(struct tlsv1_client *conn, - const u8 *key, size_t key_len) -{ - if (key_len > TLS_MASTER_SECRET_LEN) - return -1; - wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: master_secret from session " - "ticket", key, key_len); - os_memcpy(conn->master_secret, key, key_len); - conn->ticket_key = 1; - - 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) -{ -#ifdef EAP_FAST - 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; - suites[count++] = TLS_DH_anon_WITH_AES_256_CBC_SHA; - 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; -#else /* EAP_FAST */ - return -1; -#endif /* EAP_FAST */ -} - - -static int tlsv1_client_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 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_client_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_client_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_client_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_client_set_cert_chain(struct x509_certificate **chain, - const char *cert, const u8 *cert_blob, - size_t cert_blob_len) -{ - if (cert_blob) - return tlsv1_client_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_client_add_cert(chain, buf, len); - os_free(buf); - return ret; - } - - return 0; -} - - -/** - * tlsv1_client_set_ca_cert - Set trusted CA certificate(s) - * @conn: TLSv1 client connection data from tlsv1_client_init() - * @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_client_set_ca_cert(struct tlsv1_client *conn, const char *cert, - const u8 *cert_blob, size_t cert_blob_len, - const char *path) -{ - if (tlsv1_client_set_cert_chain(&conn->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_client_set_client_cert - Set client certificate - * @conn: TLSv1 client connection data from tlsv1_client_init() - * @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 - * Returns: 0 on success, -1 on failure - */ -int tlsv1_client_set_client_cert(struct tlsv1_client *conn, const char *cert, - const u8 *cert_blob, size_t cert_blob_len) -{ - return tlsv1_client_set_cert_chain(&conn->client_cert, cert, - cert_blob, cert_blob_len); -} - - -static int tlsv1_client_set_key(struct tlsv1_client *conn, - const u8 *key, size_t len) -{ - conn->client_key = crypto_private_key_import(key, len); - if (conn->client_key == NULL) { - wpa_printf(MSG_INFO, "TLSv1: Failed to parse private key"); - return -1; - } - return 0; -} - - -/** - * tlsv1_client_set_private_key - Set client private key - * @conn: TLSv1 client connection data from tlsv1_client_init() - * @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_client_set_private_key(struct tlsv1_client *conn, - const char *private_key, - const char *private_key_passwd, - const u8 *private_key_blob, - size_t private_key_blob_len) -{ - crypto_private_key_free(conn->client_key); - conn->client_key = NULL; - - if (private_key_blob) - return tlsv1_client_set_key(conn, private_key_blob, - private_key_blob_len); - - 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_client_set_key(conn, buf, len); - os_free(buf); - return ret; - } - - return 0; -} diff --git a/contrib/wpa_supplicant/tlsv1_client.h b/contrib/wpa_supplicant/tlsv1_client.h deleted file mode 100644 index dced874d1bfc..000000000000 --- a/contrib/wpa_supplicant/tlsv1_client.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * wpa_supplicant: TLSv1 client (RFC 2246) - * Copyright (c) 2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 - -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); -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_set_master_key(struct tlsv1_client *conn, - const u8 *key, size_t key_len); -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_ca_cert(struct tlsv1_client *conn, const char *cert, - const u8 *cert_blob, size_t cert_blob_len, - const char *path); -int tlsv1_client_set_client_cert(struct tlsv1_client *conn, const char *cert, - const u8 *cert_blob, size_t cert_blob_len); -int tlsv1_client_set_private_key(struct tlsv1_client *conn, - const char *private_key, - const char *private_key_passwd, - const u8 *private_key_blob, - size_t private_key_blob_len); - -#endif /* TLSV1_CLIENT_H */ diff --git a/contrib/wpa_supplicant/tlsv1_common.c b/contrib/wpa_supplicant/tlsv1_common.c deleted file mode 100644 index 8432398bf517..000000000000 --- a/contrib/wpa_supplicant/tlsv1_common.c +++ /dev/null @@ -1,552 +0,0 @@ -/* - * wpa_supplicant/hostapd: TLSv1 common routines - * Copyright (c) 2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "sha1.h" -#include "crypto.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; -} - - -static 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; -} - - -/** - * 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; -} - - -/** - * 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_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/contrib/wpa_supplicant/tlsv1_common.h b/contrib/wpa_supplicant/tlsv1_common.h deleted file mode 100644 index 9ecabfa2762b..000000000000 --- a/contrib/wpa_supplicant/tlsv1_common.h +++ /dev/null @@ -1,233 +0,0 @@ -/* - * wpa_supplicant/hostapd: TLSv1 common definitions - * Copyright (c) 2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 -#define TLSV1_COMMON - -#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 -#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 -}; - -/* HandshakeType */ -enum { - TLS_HANDSHAKE_TYPE_HELLO_REQUEST = 0, - TLS_HANDSHAKE_TYPE_CLIENT_HELLO = 1, - TLS_HANDSHAKE_TYPE_SERVER_HELLO = 2, - 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 -}; - -/* 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 - -/* ChangeCipherSpec */ -enum { - TLS_CHANGE_CIPHER_SPEC = 1 -}; - -/* TLS Extensions */ -#define TLS_EXT_PAC_OPAQUE 35 - - -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 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; -}; - - -const struct tls_cipher_suite * tls_get_cipher_suite(u16 suite); -int tls_parse_cert(const u8 *buf, size_t len, struct crypto_public_key **pk); -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_COMMON_H */ diff --git a/contrib/wpa_supplicant/todo.txt b/contrib/wpa_supplicant/todo.txt deleted file mode 100644 index edfff4fd1673..000000000000 --- a/contrib/wpa_supplicant/todo.txt +++ /dev/null @@ -1,124 +0,0 @@ -To do: -- hostap: try other roaming modes - NOTE: current mode (manual roaming) does not really roam at all.. - Firmware did not notice the current AP disappearing.. -- add support for WPA with ap_scan=0 (update selected cipher etc. based on - AssocInfo; make sure these match with configuration) -- optional security separation (build time option): run EAPOL state machines - as non-root (need to add something like socketpair between privileged root - process and non-root handler; send EAPOL packets between processes - and send keying data from non-root -> privileged) - EAPOL-Key processing (WPA & WEP keys) could be in privileged part - at least in the beginning; some parts might end up being moved to - non-root part eventually -- consider closing smart card / PCSC connection when EAP-SIM/EAP-AKA - authentication has been completed (cache scard data based on serial#(?) - and try to optimize next connection if the same card is present for next - auth) -- EAP-AKA: AT_CHECKCODE -- EAP-SIM/AKA: AT_RESULT_IND -- on disconnect event, could try to associate with another AP if one is - present in scan results; would need to update scan results periodically.. -- if driver/hw is not WPA2 capable, must remove WPA_PROTO_RSN flag from - ssid->proto fields to avoid detecting downgrade attacks when the driver - is not reporting RSN IE, but msg 3/4 has one -- Cisco AP and non-zero keyidx for unicast -> map to broadcast - (actually, this already works with driver_ndis; so maybe just change - driver_*.c to do the mapping for drivers that cannot handle non-zero keyidx - for unicast); worked also with Host AP driver and madwifi -- IEEE 802.1X and key update with driver_ndis?? wpa_supplicant did not seem - to see unencrypted EAPOL-Key frames at all.. -- EAP-PAX with PAX_SEC -- EAP (RFC 3748) - * OTP Extended Responses (Sect. 5.5) -- test what happens if authenticator sends EAP-Success before real EAP - authentication ("canned" Success); this should be ignored based on - RFC 3748 Sect. 4.2 -- test compilation with gcc -W options (more warnings?) - (Done once; number of unused function arguments still present) -- add proper support for using dot11RSNAConfigSATimeout -- ctrl_iface: get/set/remove blob -- use doc/docbook/*.sgml and docbook2{txt,html,pdf} to replace README and - web pages including the same information.. i.e., have this information only - in one page; how to build a PDF file with all the SGML included? -- test wait-for-interface and daemonize combinations with number of driver - interfaces - * 'test' worked with WPA-PSK -- EAP-POTP/RSA SecurID profile (draft-nystrom-eap-potp-03.txt) -- document wpa_gui build and consider adding it to 'make install' -- test madwifi with pairwise=TKIP group=WEP104 -- possibility to link in WPA Authenticator state machine to wpa_supplicant - (new STAKey handshake, WPA2 IBSS) -- consider merging hostapd and wpa_supplicant PMKSA cache implementations -- add support for configuring password for MSCHAPv2 as NtPasswordHash in - the same way as was added to hostapd (hash:<hex value>) -- test_driver: configure directory and create AP-<mac> and STA-<mac> files - there to allow scanning multiple APs (e.g., for testing pre-auth and PMKSA - caching testing) and to exchange STA-STA EAPOL frames -- consider adding generic buffer functionality that could be used in number - of places - * allocate buffer (with default max size), allow reserving head room to - make it possible to add a header without having to reallocate buffer - * reallocate buffer (add head and/or tail room) - * ref count and free when count=0 ? - * add data (to tail): re-alloc more tailroom if needed and copy new data - * error flag so that caller can do multiple add()s and only in the end - check whether something has failed; this should make error handling - simpler -- consider redesigning pending EAP requests (identity/password/otp from - ctrl_iface) by moving the retrying of the previous request into EAP - state machine so that EAPOL state machine is not needed for this -- rfc4284.txt (network selection for eap) -- www pages about configuring wpa_supplicant: - * global options (ap_scan, ctrl_interfaces) based on OS/driver - * network block - * key_mgmt selection - * WPA parameters - * EAP options (one page for each method) - * "configuration wizard" (step 1: select OS, step 2: select driver, ...) to - generate example configuration -- error path in rsn_preauth_init: should probably deinit l2_packet handlers - if something fails; does something else need deinit? -- consider moving SIM card functionality (IMSI fetching) away from eap.c; - this should likely happen before EAP is initialized for authentication; - now IMSI is read only after receiving EAP-Identity/Request, but since it is - really needed for all cases, reading IMSI and generating Identity string - could very well be done before EAP has been started -- test all allowed EAP Phase 2 methods (i.e., anything else than PEAP, TTLS, - FAST): SIM AKA PAX PSK LEAP; if these work, include in eap_testing.txt; if - not, either fix or make eap_allowed_phase2_type reject -- try to work around race in receiving association event and first EAPOL - message -- helper function to do memcmp(addr, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) -- add wpa_secure_memzero() macro and secure implementation (volatile u8*) to - clear memory; this would be used to clear temporary buffers containing - private data (e.g., keys); the macro can be defined to NOP in order to save - space (i.e., no code should depend on the macro doing something) -- make sure that TLS session cache is not shared between EAP types or if it - is, that the cache entries are bound to only one EAP type; e.g., cache entry - created with EAP-TLS must not be allowed to do fast re-auth with EAP-TTLS -- consider moving eap_tls_build_ack() call into eap_tls_process_helper() - (it seems to be called always if helper returns 1) - * could need to modify eap_{ttls,peap,fast}_decrypt to do same -- add support for fetching full user cert chain from Windows certificate - stores even when there are intermediate CA certs that are not in the - configured ca_cert store (e.g., ROOT) (they could be, e.g., in CA store) - - -0.6.x branch: -- clean up common.[ch] -- change TLS/crypto library interface to use a structure of function - pointers and helper inline functions (like driver_ops) instead of - requiring every TLS wrapper to implement all functions -- move from CVS to git (0.3.x, 0.4.x, 0.5.x releases will continue - to be updated only on CVS) -- move files into subdirectories and combine wpa_supplicant and hostapd - into a repository that matches in directory structure with the release - tarballs - (subdirs: eap_common, eap_peer, eap_server, driver, driver_ap, ...) -- make it clearer that EAP server/peer can be used as a separate library - for other programs -- add support for encrypted configuration fields (e.g., password, psk, - passphrase, pin) -- wpa_gui: add support for setting and showing priority, id_str, auth_alg - (open/shared for static WEP) diff --git a/contrib/wpa_supplicant/version.h b/contrib/wpa_supplicant/version.h deleted file mode 100644 index fa00fcca0f7d..000000000000 --- a/contrib/wpa_supplicant/version.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef VERSION_H -#define VERSION_H - -#define VERSION_STR "0.5.11" - -#endif /* VERSION_H */ diff --git a/contrib/wpa_supplicant/wpa.c b/contrib/wpa_supplicant/wpa.c deleted file mode 100644 index 7ef746a95acc..000000000000 --- a/contrib/wpa_supplicant/wpa.c +++ /dev/null @@ -1,4317 +0,0 @@ -/* - * WPA Supplicant - WPA state machine and EAPOL-Key processing - * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "sha1.h" -#include "rc4.h" -#include "aes_wrap.h" -#include "wpa.h" -#include "eloop.h" -#include "config.h" -#include "l2_packet.h" -#include "eapol_sm.h" -#include "preauth.h" -#include "pmksa_cache.h" -#include "wpa_i.h" - - -static const int WPA_SELECTOR_LEN = 4; -static const u8 WPA_OUI_TYPE[] = { 0x00, 0x50, 0xf2, 1 }; -static const u16 WPA_VERSION = 1; -static const u8 WPA_AUTH_KEY_MGMT_NONE[] = { 0x00, 0x50, 0xf2, 0 }; -static const u8 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X[] = { 0x00, 0x50, 0xf2, 1 }; -static const u8 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X[] = { 0x00, 0x50, 0xf2, 2 }; -static const u8 WPA_CIPHER_SUITE_NONE[] = { 0x00, 0x50, 0xf2, 0 }; -static const u8 WPA_CIPHER_SUITE_WEP40[] = { 0x00, 0x50, 0xf2, 1 }; -static const u8 WPA_CIPHER_SUITE_TKIP[] = { 0x00, 0x50, 0xf2, 2 }; -#if 0 -static const u8 WPA_CIPHER_SUITE_WRAP[] = { 0x00, 0x50, 0xf2, 3 }; -#endif -static const u8 WPA_CIPHER_SUITE_CCMP[] = { 0x00, 0x50, 0xf2, 4 }; -static const u8 WPA_CIPHER_SUITE_WEP104[] = { 0x00, 0x50, 0xf2, 5 }; - -/* 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) - */ - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -struct wpa_ie_hdr { - u8 elem_id; - u8 len; - u8 oui[4]; /* 24-bit OUI followed by 8-bit OUI type */ - u8 version[2]; -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - - -static const int RSN_SELECTOR_LEN = 4; -static const u16 RSN_VERSION = 1; -static const u8 RSN_AUTH_KEY_MGMT_UNSPEC_802_1X[] = { 0x00, 0x0f, 0xac, 1 }; -static const u8 RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X[] = { 0x00, 0x0f, 0xac, 2 }; -static const u8 RSN_CIPHER_SUITE_NONE[] = { 0x00, 0x0f, 0xac, 0 }; -static const u8 RSN_CIPHER_SUITE_WEP40[] = { 0x00, 0x0f, 0xac, 1 }; -static const u8 RSN_CIPHER_SUITE_TKIP[] = { 0x00, 0x0f, 0xac, 2 }; -#if 0 -static const u8 RSN_CIPHER_SUITE_WRAP[] = { 0x00, 0x0f, 0xac, 3 }; -#endif -static const u8 RSN_CIPHER_SUITE_CCMP[] = { 0x00, 0x0f, 0xac, 4 }; -static const u8 RSN_CIPHER_SUITE_WEP104[] = { 0x00, 0x0f, 0xac, 5 }; -#ifdef CONFIG_IEEE80211W -static const u8 RSN_CIPHER_SUITE_AES_128_CMAC[] = { 0x00, 0x0f, 0xac, 6 }; -#endif /* CONFIG_IEEE80211W */ - -/* EAPOL-Key Key Data Encapsulation - * GroupKey and PeerKey require encryption, otherwise, encryption is optional. - */ -static const u8 RSN_KEY_DATA_GROUPKEY[] = { 0x00, 0x0f, 0xac, 1 }; -#if 0 -static const u8 RSN_KEY_DATA_STAKEY[] = { 0x00, 0x0f, 0xac, 2 }; -#endif -static const u8 RSN_KEY_DATA_MAC_ADDR[] = { 0x00, 0x0f, 0xac, 3 }; -static const u8 RSN_KEY_DATA_PMKID[] = { 0x00, 0x0f, 0xac, 4 }; -#ifdef CONFIG_PEERKEY -static const u8 RSN_KEY_DATA_SMK[] = { 0x00, 0x0f, 0xac, 5 }; -static const u8 RSN_KEY_DATA_NONCE[] = { 0x00, 0x0f, 0xac, 6 }; -static const u8 RSN_KEY_DATA_LIFETIME[] = { 0x00, 0x0f, 0xac, 7 }; -static const u8 RSN_KEY_DATA_ERROR[] = { 0x00, 0x0f, 0xac, 8 }; -#endif /* CONFIG_PEERKEY */ -#ifdef CONFIG_IEEE80211W -/* FIX: IEEE 802.11w/D1.0 is using subtypes 5 and 6 for these, but they were - * already taken by 802.11ma (PeerKey). Need to update the values here once - * IEEE 802.11w fixes these. */ -static const u8 RSN_KEY_DATA_DHV[] = { 0x00, 0x0f, 0xac, 9 }; -static const u8 RSN_KEY_DATA_IGTK[] = { 0x00, 0x0f, 0xac, 10 }; -#endif /* CONFIG_IEEE80211W */ - -#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 */ - -/* 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) - */ - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -struct rsn_ie_hdr { - u8 elem_id; /* WLAN_EID_RSN */ - u8 len; - u8 version[2]; -} STRUCT_PACKED; - - -struct wpa_eapol_key { - u8 type; - /* Note: key_info, key_length, and key_data_length are unaligned */ - u8 key_info[2]; - u8 key_length[2]; - u8 replay_counter[WPA_REPLAY_COUNTER_LEN]; - u8 key_nonce[WPA_NONCE_LEN]; - u8 key_iv[16]; - u8 key_rsc[8]; - u8 key_id[8]; /* Reserved in IEEE 802.11i/RSN */ - u8 key_mic[16]; - u8 key_data_length[2]; - /* followed by key_data_length bytes of key_data */ -} STRUCT_PACKED; - - -struct rsn_error_kde { - u16 mui; - u16 error_type; -} STRUCT_PACKED; - -#ifdef CONFIG_IEEE80211W -struct wpa_dhv_kde { - u8 dhv[WPA_DHV_LEN]; -} STRUCT_PACKED; - -struct wpa_igtk_kde { - u8 keyid[2]; - u8 pn[6]; - u8 igtk[WPA_IGTK_LEN]; -} STRUCT_PACKED; -#endif /* CONFIG_IEEE80211W */ - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - -#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_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) - - -#ifdef CONFIG_PEERKEY -static void wpa_supplicant_peerkey_free(struct wpa_sm *sm, - struct wpa_peerkey *peerkey); -#endif /* CONFIG_PEERKEY */ - - -/** - * 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 - */ -static 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"; - 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 - */ -static const char * wpa_key_mgmt_txt(int key_mgmt, int proto) -{ - switch (key_mgmt) { - case WPA_KEY_MGMT_IEEE8021X: - return proto == WPA_PROTO_RSN ? - "WPA2/IEEE 802.1X/EAP" : "WPA/IEEE 802.1X/EAP"; - case WPA_KEY_MGMT_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)"; - default: - return "UNKNOWN"; - } -} - - -static int wpa_selector_to_bitfield(const u8 *s) -{ - if (os_memcmp(s, WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN) == 0) - return WPA_CIPHER_NONE; - if (os_memcmp(s, WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN) == 0) - return WPA_CIPHER_WEP40; - if (os_memcmp(s, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN) == 0) - return WPA_CIPHER_TKIP; - if (os_memcmp(s, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN) == 0) - return WPA_CIPHER_CCMP; - if (os_memcmp(s, WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN) == 0) - return WPA_CIPHER_WEP104; - return 0; -} - - -static int wpa_key_mgmt_to_bitfield(const u8 *s) -{ - if (os_memcmp(s, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X, WPA_SELECTOR_LEN) == - 0) - return WPA_KEY_MGMT_IEEE8021X; - if (os_memcmp(s, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X, WPA_SELECTOR_LEN) - == 0) - return WPA_KEY_MGMT_PSK; - if (os_memcmp(s, WPA_AUTH_KEY_MGMT_NONE, WPA_SELECTOR_LEN) == 0) - return WPA_KEY_MGMT_WPA_NONE; - return 0; -} - - -#ifndef CONFIG_NO_WPA2 -static int rsn_selector_to_bitfield(const u8 *s) -{ - if (os_memcmp(s, RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN) == 0) - return WPA_CIPHER_NONE; - if (os_memcmp(s, RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN) == 0) - return WPA_CIPHER_WEP40; - if (os_memcmp(s, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN) == 0) - return WPA_CIPHER_TKIP; - if (os_memcmp(s, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN) == 0) - return WPA_CIPHER_CCMP; - if (os_memcmp(s, RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN) == 0) - return WPA_CIPHER_WEP104; -#ifdef CONFIG_IEEE80211W - if (os_memcmp(s, RSN_CIPHER_SUITE_AES_128_CMAC, RSN_SELECTOR_LEN) == 0) - return WPA_CIPHER_AES_128_CMAC; -#endif /* CONFIG_IEEE80211W */ - return 0; -} - - -static int rsn_key_mgmt_to_bitfield(const u8 *s) -{ - if (os_memcmp(s, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X, RSN_SELECTOR_LEN) == - 0) - return WPA_KEY_MGMT_IEEE8021X; - if (os_memcmp(s, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X, RSN_SELECTOR_LEN) - == 0) - return WPA_KEY_MGMT_PSK; - return 0; -} -#endif /* CONFIG_NO_WPA2 */ - - -#ifdef CONFIG_PEERKEY -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, const u8 *kde, const u8 *data, - size_t data_len) -{ - *pos++ = GENERIC_INFO_ELEM; - *pos++ = RSN_SELECTOR_LEN + data_len; - os_memcpy(pos, kde, RSN_SELECTOR_LEN); - pos += RSN_SELECTOR_LEN; - os_memcpy(pos, data, data_len); - pos += data_len; - return pos; -} -#endif /* CONFIG_PEERKEY */ - - -static 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; - - 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 != GENERIC_INFO_ELEM || - hdr->len != wpa_ie_len - 2 || - os_memcmp(hdr->oui, WPA_OUI_TYPE, WPA_SELECTOR_LEN) != 0 || - WPA_GET_LE16(hdr->version) != WPA_VERSION) { - wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version", - __func__); - return -1; - } - - 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 -1; - } - - 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 -1; - } - 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 -1; - } - - 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 -1; - } - 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 -1; - } - - 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; -} - - -static 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; - - 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 != RSN_INFO_ELEM || - 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 -1; - } - - 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 -1; - } - - 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 -1; - } - 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 -1; - } - - 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 -1; - } - 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 -1; - } - - 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 < data->num_pmkid * PMKID_LEN) { - wpa_printf(MSG_DEBUG, "%s: PMKID underflow " - "(num_pmkid=%d left=%d)", - __func__, data->num_pmkid, left); - data->num_pmkid = 0; - } 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 -1; - } - 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 */ -} - - -/** - * 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] == RSN_INFO_ELEM) - 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 = GENERIC_INFO_ELEM; - os_memcpy(hdr->oui, WPA_OUI_TYPE, WPA_SELECTOR_LEN); - WPA_PUT_LE16(hdr->version, WPA_VERSION); - pos = (u8 *) (hdr + 1); - - if (group_cipher == WPA_CIPHER_CCMP) { - os_memcpy(pos, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN); - } else if (group_cipher == WPA_CIPHER_TKIP) { - os_memcpy(pos, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN); - } else if (group_cipher == WPA_CIPHER_WEP104) { - os_memcpy(pos, WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN); - } else if (group_cipher == WPA_CIPHER_WEP40) { - os_memcpy(pos, WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN); - } 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) { - os_memcpy(pos, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN); - } else if (pairwise_cipher == WPA_CIPHER_TKIP) { - os_memcpy(pos, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN); - } else if (pairwise_cipher == WPA_CIPHER_NONE) { - os_memcpy(pos, WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN); - } 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) { - os_memcpy(pos, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X, - WPA_SELECTOR_LEN); - } else if (key_mgmt == WPA_KEY_MGMT_PSK) { - os_memcpy(pos, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X, - WPA_SELECTOR_LEN); - } else if (key_mgmt == WPA_KEY_MGMT_WPA_NONE) { - os_memcpy(pos, WPA_AUTH_KEY_MGMT_NONE, WPA_SELECTOR_LEN); - } 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)) - return -1; - - hdr = (struct rsn_ie_hdr *) rsn_ie; - hdr->elem_id = RSN_INFO_ELEM; - WPA_PUT_LE16(hdr->version, RSN_VERSION); - pos = (u8 *) (hdr + 1); - - if (group_cipher == WPA_CIPHER_CCMP) { - os_memcpy(pos, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN); - } else if (group_cipher == WPA_CIPHER_TKIP) { - os_memcpy(pos, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN); - } else if (group_cipher == WPA_CIPHER_WEP104) { - os_memcpy(pos, RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN); - } else if (group_cipher == WPA_CIPHER_WEP40) { - os_memcpy(pos, RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN); - } 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) { - os_memcpy(pos, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN); - } else if (pairwise_cipher == WPA_CIPHER_TKIP) { - os_memcpy(pos, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN); - } else if (pairwise_cipher == WPA_CIPHER_NONE) { - os_memcpy(pos, RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN); - } 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) { - os_memcpy(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X, - RSN_SELECTOR_LEN); - } else if (key_mgmt == WPA_KEY_MGMT_PSK) { - os_memcpy(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X, - RSN_SELECTOR_LEN); - } 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 (mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) - capab |= WPA_CAPABILITY_MGMT_FRAME_PROTECTION; -#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 */ - memcpy(pos, RSN_CIPHER_SUITE_AES_128_CMAC, - RSN_SELECTOR_LEN); - 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 - */ -static 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_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 - * - * 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)) - */ -static 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) -{ - u8 data[2 * ETH_ALEN + 2 * 32]; - - 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, 32) < 0) { - os_memcpy(data + 2 * ETH_ALEN, nonce1, 32); - os_memcpy(data + 2 * ETH_ALEN + 32, nonce2, 32); - } else { - os_memcpy(data + 2 * ETH_ALEN, nonce2, 32); - os_memcpy(data + 2 * ETH_ALEN + 32, nonce1, 32); - } - - sha1_prf(pmk, pmk_len, label, data, sizeof(data), ptk, ptk_len); - - wpa_hexdump_key(MSG_DEBUG, "WPA: PMK", pmk, pmk_len); - wpa_hexdump_key(MSG_DEBUG, "WPA: PTK", ptk, ptk_len); -} - - -/** - * 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 - * - * 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). - */ -static void wpa_eapol_key_mic(const u8 *key, int ver, - const u8 *buf, size_t len, u8 *mic) -{ - if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) { - hmac_md5(key, 16, buf, len, mic); - } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { - u8 hash[SHA1_MAC_LEN]; - hmac_sha1(key, 16, buf, len, hash); - os_memcpy(mic, hash, MD5_MAC_LEN); - } -} - - -static 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 (os_memcmp(dest, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0 && - os_memcmp(sm->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0) { - /* - * Association event was not yet received; try to fetch - * BSSID from the driver. - */ - if (wpa_sm_get_bssid(sm, sm->bssid) < 0) { - wpa_printf(MSG_DEBUG, "WPA: Failed to read BSSID for " - "EAPOL-Key destination address"); - } else { - dest = sm->bssid; - wpa_printf(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_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); - 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 - * Returns: Pointer to the current network structure or %NULL on failure - * - * 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 (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 " - "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_printf(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); -} - - -/** - * 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) -{ -#ifdef CONFIG_PEERKEY - 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 wpa_ssid *ssid = sm->cur_ssid; - struct rsn_ie_hdr *hdr; - struct wpa_peerkey *peerkey; - struct wpa_ie_data ie; - - if (sm->proto != WPA_PROTO_RSN || !sm->ptk_set || - ssid == NULL || !ssid->peerkey) - 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_malloc(sizeof(*peerkey)); - if (peerkey == NULL) - return -1; - os_memset(peerkey, 0, sizeof(*peerkey)); - peerkey->initiator = 1; - os_memcpy(peerkey->addr, peer, ETH_ALEN); - - /* 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 = RSN_INFO_ELEM; - 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. */ - os_memcpy(pos, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN); - pos += RSN_SELECTOR_LEN; - count_pos = pos; - pos += 2; - - count = 0; - if (ssid->pairwise_cipher & WPA_CIPHER_CCMP) { - os_memcpy(pos, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN); - pos += RSN_SELECTOR_LEN; - count++; - } - if (ssid->pairwise_cipher & WPA_CIPHER_TKIP) { - os_memcpy(pos, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN); - 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 (hostapd_get_rand(peerkey->inonce, WPA_NONCE_LEN)) { - wpa_msg(sm->ctx->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 */ - pos = 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; - -#else /* CONFIG_PEERKEY */ - - return -1; - -#endif /* CONFIG_PEERKEY */ -} - - -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 *dhv; - size_t dhv_len; - const u8 *igtk; - size_t igtk_len; -#endif /* CONFIG_IEEE80211W */ -}; - - -/** - * wpa_supplicant_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_supplicant_parse_generic(const u8 *pos, const u8 *end, - struct wpa_eapol_ie_parse *ie) -{ - if (pos[1] == 0) - return 1; - - if (pos[1] >= 6 && - os_memcmp(pos + 2, WPA_OUI_TYPE, WPA_SELECTOR_LEN) == 0 && - 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 && - os_memcmp(pos + 2, RSN_KEY_DATA_PMKID, RSN_SELECTOR_LEN) == 0) { - ie->pmkid = pos + 2 + RSN_SELECTOR_LEN; - return 0; - } - - if (pos[1] > RSN_SELECTOR_LEN + 2 && - os_memcmp(pos + 2, RSN_KEY_DATA_GROUPKEY, RSN_SELECTOR_LEN) == 0) { - ie->gtk = pos + 2 + RSN_SELECTOR_LEN; - ie->gtk_len = pos[1] - RSN_SELECTOR_LEN; - return 0; - } - - if (pos[1] > RSN_SELECTOR_LEN + 2 && - os_memcmp(pos + 2, RSN_KEY_DATA_MAC_ADDR, RSN_SELECTOR_LEN) == 0) { - 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 && - os_memcmp(pos + 2, RSN_KEY_DATA_SMK, RSN_SELECTOR_LEN) == 0) { - ie->smk = pos + 2 + RSN_SELECTOR_LEN; - ie->smk_len = pos[1] - RSN_SELECTOR_LEN; - return 0; - } - - if (pos[1] > RSN_SELECTOR_LEN + 2 && - os_memcmp(pos + 2, RSN_KEY_DATA_NONCE, RSN_SELECTOR_LEN) == 0) { - ie->nonce = pos + 2 + RSN_SELECTOR_LEN; - ie->nonce_len = pos[1] - RSN_SELECTOR_LEN; - return 0; - } - - if (pos[1] > RSN_SELECTOR_LEN + 2 && - os_memcmp(pos + 2, RSN_KEY_DATA_LIFETIME, RSN_SELECTOR_LEN) == 0) { - ie->lifetime = pos + 2 + RSN_SELECTOR_LEN; - ie->lifetime_len = pos[1] - RSN_SELECTOR_LEN; - return 0; - } - - if (pos[1] > RSN_SELECTOR_LEN + 2 && - os_memcmp(pos + 2, RSN_KEY_DATA_ERROR, RSN_SELECTOR_LEN) == 0) { - 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 && - os_memcmp(pos + 2, RSN_KEY_DATA_DHV, RSN_SELECTOR_LEN) == 0) { - ie->dhv = pos + 2 + RSN_SELECTOR_LEN; - ie->dhv_len = pos[1] - RSN_SELECTOR_LEN; - return 0; - } - - if (pos[1] > RSN_SELECTOR_LEN + 2 && - os_memcmp(pos + 2, RSN_KEY_DATA_IGTK, RSN_SELECTOR_LEN) == 0) { - ie->igtk = pos + 2 + RSN_SELECTOR_LEN; - ie->igtk_len = pos[1] - RSN_SELECTOR_LEN; - 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 - */ -static 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 == RSN_INFO_ELEM) { - ie->rsn_ie = pos; - ie->rsn_ie_len = pos[1] + 2; - } else if (*pos == GENERIC_INFO_ELEM) { - ret = wpa_supplicant_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; -} - - -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_printf(MSG_DEBUG, "RSN: found matching PMKID from " - "PMKSA cache"); - } else { - wpa_printf(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); - } else if (sm->key_mgmt == WPA_KEY_MGMT_IEEE8021X && 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; - } - if (res == 0) { - wpa_hexdump_key(MSG_DEBUG, "WPA: PMK from EAPOL state " - "machines", sm->pmk, pmk_len); - sm->pmk_len = pmk_len; - pmksa_cache_add(sm->pmksa, sm->pmk, pmk_len, src_addr, - sm->own_addr, sm->cur_ssid); - if (!sm->cur_pmksa && pmkid && - pmksa_cache_get(sm->pmksa, src_addr, pmkid)) { - wpa_printf(MSG_DEBUG, "RSN: the new PMK " - "matches with the PMKID"); - abort_cached = 0; - } - } else { - wpa_msg(sm->ctx->ctx, MSG_WARNING, - "WPA: Failed to get master session key from " - "EAPOL state machines"); - wpa_msg(sm->ctx->ctx, MSG_WARNING, - "WPA: Key handshake aborted"); - if (sm->cur_pmksa) { - wpa_printf(MSG_DEBUG, "RSN: Cancelled PMKSA " - "caching attempt"); - sm->cur_pmksa = NULL; - abort_cached = 1; - } else if (!abort_cached) { - return -1; - } - } - } - - if (abort_cached && sm->key_mgmt == WPA_KEY_MGMT_IEEE8021X) { - /* Send EAPOL-Start to trigger full EAP authentication. */ - u8 *buf; - size_t buflen; - - wpa_printf(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 -1; - } - - return 0; -} - - -static 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; - - if (wpa_ie == NULL) { - wpa_printf(MSG_WARNING, "WPA: No wpa_ie set - cannot " - "generate msg 2/4"); - return -1; - } - - 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) - 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_PUT_BE16(reply->key_data_length, wpa_ie_len); - os_memcpy(reply + 1, wpa_ie, wpa_ie_len); - - os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN); - - wpa_printf(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 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]; - - if (wpa_sm_get_ssid(sm) == NULL) { - wpa_printf(MSG_WARNING, "WPA: No SSID info found (msg 1 of " - "4)."); - return; - } - - wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE); - wpa_printf(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 */ - - if (wpa_supplicant_get_pmk(sm, src_addr, ie.pmkid)) - return; - - if (sm->renew_snonce) { - if (hostapd_get_rand(sm->snonce, WPA_NONCE_LEN)) { - wpa_msg(sm->ctx->ctx, MSG_WARNING, - "WPA: Failed to get random data for SNonce"); - return; - } - 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_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion", - sm->own_addr, sm->bssid, sm->snonce, key->key_nonce, - (u8 *) ptk, sizeof(*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)) - return; - - os_memcpy(sm->anonce, key->key_nonce, WPA_NONCE_LEN); -} - - -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->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 (sm->key_mgmt == WPA_KEY_MGMT_PSK) - 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_printf(MSG_DEBUG, "RSN: Authenticator accepted " - "opportunistic PMKSA entry - marking it valid"); - sm->cur_pmksa->opportunistic = 0; - } -} - - -static int wpa_supplicant_install_ptk(struct wpa_sm *sm, - const struct wpa_eapol_key *key) -{ - int keylen, rsclen; - wpa_alg alg; - const u8 *key_rsc; - u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - - wpa_printf(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_printf(MSG_DEBUG, "WPA: Pairwise Cipher Suite: " - "NONE - do not use pairwise keys"); - return 0; - default: - wpa_printf(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_printf(MSG_WARNING, "WPA: Failed to set PTK to the " - "driver."); - return -1; - } - return 0; -} - - -static int wpa_supplicant_check_group_cipher(int group_cipher, - int keylen, int maxkeylen, - int *key_rsc_len, 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_printf(MSG_WARNING, "WPA: Unsupported Group Cipher %d", - group_cipher); - return -1; - } - - if (ret < 0 ) { - wpa_printf(MSG_WARNING, "WPA: Unsupported %s Group Cipher key " - "length %d (%d).", - wpa_cipher_txt(group_cipher), keylen, maxkeylen); - } - - return ret; -} - - -struct wpa_gtk_data { - 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_printf(MSG_DEBUG, "WPA: Installing GTK to the driver " - "(keyidx=%d tx=%d).", gd->keyidx, gd->tx); - 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, - (u8 *) "\xff\xff\xff\xff\xff\xff", - gd->keyidx, 1, key_rsc, gd->key_rsc_len, - _gtk, gd->gtk_len) < 0) { - wpa_printf(MSG_WARNING, "WPA: Failed to set " - "GTK to the driver (Group only)."); - return -1; - } - } else if (wpa_sm_set_key(sm, gd->alg, - (u8 *) "\xff\xff\xff\xff\xff\xff", - gd->keyidx, gd->tx, key_rsc, gd->key_rsc_len, - _gtk, gd->gtk_len) < 0) { - wpa_printf(MSG_WARNING, "WPA: Failed to set GTK to " - "the driver."); - 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_printf(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->group_cipher, - gtk_len, gtk_len, - &gd.key_rsc_len, &gd.alg) || - wpa_supplicant_install_gtk(sm, &gd, key->key_rsc)) { - wpa_printf(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_printf(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_printf(MSG_WARNING, "WPA: Invalid IGTK KeyID %d", - keyidx); - return -1; - } - if (wpa_sm_set_key(sm, WPA_ALG_IGTK, - (u8 *) "\xff\xff\xff\xff\xff\xff", - keyidx, 0, igtk->pn, sizeof(igtk->pn), - igtk->igtk, WPA_IGTK_LEN) < 0) { - wpa_printf(MSG_WARNING, "WPA: Failed to configure IGTK" - " to the driver"); - return -1; - } - } - - if (ie->dhv) { - const struct wpa_dhv_kde *dhv; - if (ie->dhv_len != sizeof(*dhv)) - return -1; - dhv = (const struct wpa_dhv_kde *) ie->dhv; - wpa_hexdump_key(MSG_DEBUG, "WPA: DHV", dhv->dhv, WPA_DHV_LEN); - if (wpa_sm_set_key(sm, WPA_ALG_DHV, - (u8 *) "\xff\xff\xff\xff\xff\xff", 0, 0, - NULL, 0, dhv->dhv, WPA_DHV_LEN) < 0) { - wpa_printf(MSG_WARNING, "WPA: Failed to configure DHV " - "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->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_printf(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_printf(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, REASON_IE_IN_4WAY_DIFFERS); -} - - -static int wpa_supplicant_validate_ie(struct wpa_sm *sm, - const unsigned char *src_addr, - struct wpa_eapol_ie_parse *ie) -{ - struct wpa_ssid *ssid = sm->cur_ssid; - - if (sm->ap_wpa_ie == NULL && sm->ap_rsn_ie == NULL) { - wpa_printf(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_printf(MSG_WARNING, "WPA: Could not find AP from " - "the scan results"); - } else { - wpa_printf(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 && - (ie->rsn_ie_len != sm->ap_rsn_ie_len || - os_memcmp(ie->rsn_ie, sm->ap_rsn_ie, ie->rsn_ie_len) != 0))) { - 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 && - ssid && (ssid->proto & WPA_PROTO_RSN)) { - 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; - } - - return 0; -} - - -static 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_printf(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_printf(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_printf(MSG_WARNING, "WPA: GTK IE in unencrypted key data"); - return; - } -#ifdef CONFIG_IEEE80211W - if ((ie.dhv || ie.igtk) && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { - wpa_printf(MSG_WARNING, "WPA: DHV/IGTK KDE in unencrypted key " - "data"); - return; - } - - if (ie.dhv && ie.dhv_len != sizeof(struct wpa_dhv_kde)) { - wpa_printf(MSG_WARNING, "WPA: Invalid DHV KDE length %lu", - (unsigned long) ie.dhv_len); - return; - } - - if (ie.igtk && ie.igtk_len != sizeof(struct wpa_igtk_kde)) { - wpa_printf(MSG_WARNING, "WPA: Invalid IGTK KDE length %lu", - (unsigned long) ie.igtk_len); - return; - } -#endif /* CONFIG_IEEE80211W */ - - if (wpa_supplicant_validate_ie(sm, sm->bssid, &ie) < 0) - return; - - if (os_memcmp(sm->anonce, key->key_nonce, WPA_NONCE_LEN) != 0) { - wpa_printf(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)); - return; - } - - keylen = WPA_GET_BE16(key->key_length); - switch (sm->pairwise_cipher) { - case WPA_CIPHER_CCMP: - if (keylen != 16) { - wpa_printf(MSG_WARNING, "WPA: Invalid CCMP key length " - "%d (src=" MACSTR ")", - keylen, MAC2STR(sm->bssid)); - return; - } - break; - case WPA_CIPHER_TKIP: - if (keylen != 32) { - wpa_printf(MSG_WARNING, "WPA: Invalid TKIP key length " - "%d (src=" MACSTR ")", - keylen, MAC2STR(sm->bssid)); - return; - } - break; - } - - if (wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info, - NULL, 0, &sm->ptk)) - return; - - /* 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) { - wpa_supplicant_install_ptk(sm, key); - } - - 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_printf(MSG_INFO, "RSN: Failed to configure GTK"); - } - - if (ieee80211w_set_keys(sm, &ie) < 0) - wpa_printf(MSG_INFO, "RSN: Failed to configure DHV/IGTK"); -} - - -#ifdef CONFIG_PEERKEY -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) -{ -#ifndef CONFIG_NO_WPA2 - 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); - pos = 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; -#else /* CONFIG_NO_WPA2 */ - return -1; -#endif /* CONFIG_NO_WPA2 */ -} - - -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 */ - pos = 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_ssid *ssid = sm->cur_ssid; - 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 (ssid == NULL || !ssid->peerkey || 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 & ssid->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_malloc(sizeof(*peerkey)); - if (peerkey == NULL) - return -1; - os_memset(peerkey, 0, sizeof(*peerkey)); - 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; - - if (hostapd_get_rand(peerkey->pnonce, WPA_NONCE_LEN)) { - wpa_msg(sm->ctx->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 = RSN_INFO_ELEM; - 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. */ - os_memcpy(pos, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN); - 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) - os_memcpy(pos, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN); - else if (cipher == WPA_CIPHER_TKIP) - os_memcpy(pos, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN); - 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 - * - * 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) -{ - 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[SHA1_MAC_LEN]; - - addr[0] = (u8 *) title; - addr[1] = pnonce; - addr[2] = mac_p; - addr[3] = inonce; - addr[4] = mac_i; - - 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 (hostapd_get_rand(peerkey->inonce, WPA_NONCE_LEN)) { - wpa_msg(sm->ctx->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; - u32 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); - pos = 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_m45( - struct wpa_sm *sm, const unsigned char *src_addr, - const struct wpa_eapol_key *key, size_t extra_len, int ver) -{ - struct wpa_ssid *ssid = sm->cur_ssid; - struct wpa_peerkey *peerkey; - struct wpa_eapol_ie_parse kde; - u32 lifetime; - struct os_time now; - struct wpa_ie_data ie; - - if (ssid == NULL || !ssid->peerkey || 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) { - int cipher; - 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 & ssid->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; - } - } else { - 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 M5 did not " - "match with the one received in SMK M2"); - 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); - 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); - } - 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_ssid *ssid = sm->cur_ssid; - 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 (ssid == NULL || !ssid->peerkey || 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); - os_memcpy(&error, kde.error, sizeof(error)); - error_type = be_to_host16(error.error_type); - wpa_msg(sm->ctx->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; - u32 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 (hostapd_get_rand(peerkey->pnonce, WPA_NONCE_LEN)) { - wpa_msg(sm->ctx->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)); - /* 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)); - pos = 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, _key + 24, 8); - os_memcpy(key_buf + 24, _key + 16, 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; - } -} -#endif /* CONFIG_PEERKEY */ - - -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_printf(MSG_WARNING, "WPA: GTK IE in unencrypted key data"); - return -1; - } - if (ie.gtk == NULL) { - wpa_printf(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->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_printf(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_printf(MSG_INFO, "RSN: Failed to configure DHV/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_printf(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_printf(MSG_INFO, "WPA: Too short maxkeylen (%lu)", - (unsigned long) maxkeylen); - return -1; - } - maxkeylen -= 8; - } - - if (wpa_supplicant_check_group_cipher(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_printf(MSG_WARNING, "WPA: RC4 key data " - "too long (%lu)", - (unsigned long) keydatalen); - return -1; - } - os_memcpy(gd->gtk, key + 1, keydatalen); - rc4_skip(ek, 32, 256, gd->gtk, keydatalen); - } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { - if (keydatalen % 8) { - wpa_printf(MSG_WARNING, "WPA: Unsupported AES-WRAP " - "len %lu", (unsigned long) keydatalen); - return -1; - } - if (maxkeylen > sizeof(gd->gtk)) { - wpa_printf(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_printf(MSG_WARNING, "WPA: AES unwrap " - "failed - could not decrypt GTK"); - 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_printf(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_printf(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) - return; - - if (wpa_supplicant_install_gtk(sm, &gd, key->key_rsc) || - wpa_supplicant_send_2_of_2(sm, key, ver, key_info)) - return; - - if (rekey) { - wpa_msg(sm->ctx->ctx, MSG_INFO, "WPA: Group rekeying " - "completed with " MACSTR " [GTK=%s]", - MAC2STR(sm->bssid), wpa_cipher_txt(sm->group_cipher)); - wpa_sm_set_state(sm, WPA_COMPLETED); - } else { - wpa_supplicant_key_neg_complete(sm, sm->bssid, - key_info & - WPA_KEY_INFO_SECURE); - } -} - - -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_printf(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_printf(MSG_WARNING, "WPA: Invalid EAPOL-Key MIC " - "- dropping packet"); - return -1; - } - ok = 1; - } - - if (!ok) { - wpa_printf(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; -} - - -#ifdef CONFIG_PEERKEY -static int wpa_supplicant_verify_eapol_key_mic_peerkey( - 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->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; -} -#endif /* CONFIG_PEERKEY */ - - -/* 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_printf(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); - rc4_skip(ek, 32, 256, (u8 *) (key + 1), keydatalen); - } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { - u8 *buf; - if (keydatalen % 8) { - wpa_printf(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_printf(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_printf(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); - } - 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_printf(MSG_DEBUG, "RSN: Cancelling PMKSA caching attempt"); - sm->cur_pmksa = NULL; - } -} - - -static void wpa_eapol_key_dump(const struct wpa_eapol_key *key) -{ -#ifndef CONFIG_NO_STDOUT_DEBUG - u16 key_info = WPA_GET_BE16(key->key_info); - - wpa_printf(MSG_DEBUG, " EAPOL-Key type=%d", key->type); - wpa_printf(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_printf(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; - - if (len < sizeof(*hdr) + sizeof(*key)) { - wpa_printf(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_printf(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_printf(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_printf(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_printf(MSG_DEBUG, "WPA: EAPOL-Key type (%d) unknown, " - "discarded", key->type); - ret = 0; - goto out; - } - wpa_eapol_key_dump(key); - - eapol_sm_notify_lower_layer_success(sm->eapol); - wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL-Key", tmp, len); - if (data_len < len) { - wpa_printf(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 && - ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { - wpa_printf(MSG_INFO, "WPA: Unsupported EAPOL-Key descriptor " - "version %d.", ver); - goto out; - } - - if (sm->pairwise_cipher == WPA_CIPHER_CCMP && - ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { - wpa_printf(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_printf(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_printf(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_printf(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_printf(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_printf(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_printf(MSG_INFO, "WPA: No Ack bit in key_info"); - goto out; - } - - if (key_info & WPA_KEY_INFO_REQUEST) { - wpa_printf(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 && - wpa_supplicant_verify_eapol_key_mic_peerkey( - 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->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_printf(MSG_WARNING, "WPA: Ignored EAPOL-Key " - "(Pairwise) with non-zero key index"); - goto out; - } -#ifdef CONFIG_PEERKEY - if (peerkey) { - 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); - } - } else -#endif /* CONFIG_PEERKEY */ - 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) { -#ifdef CONFIG_PEERKEY - 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 */ - } 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_printf(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 const u8 * wpa_key_mgmt_suite(struct wpa_sm *sm) -{ - static const u8 *dummy = (u8 *) "\x00\x00\x00\x00"; - 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); - case WPA_KEY_MGMT_WPA_NONE: - return WPA_AUTH_KEY_MGMT_NONE; - default: - return dummy; - } -} - - -static const u8 * wpa_cipher_suite(struct wpa_sm *sm, int cipher) -{ - static const u8 *dummy = (u8 *) "\x00\x00\x00\x00"; - 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 dummy; - } -} - - -#define RSN_SUITE "%02x-%02x-%02x-%d" -#define RSN_SUITE_ARG(s) (s)[0], (s)[1], (s)[2], (s)[3] - -/** - * 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 ((sm->key_mgmt == WPA_KEY_MGMT_PSK || - sm->key_mgmt == WPA_KEY_MGMT_IEEE8021X) && - 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_printf(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, 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; - 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_printf(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); - os_free(sm->assoc_wpa_ie); - os_free(sm->ap_wpa_ie); - os_free(sm->ap_rsn_ie); - os_free(sm->ctx); -#ifdef CONFIG_PEERKEY - { - struct wpa_peerkey *prev, *peerkey = sm->peerkey; - while (peerkey) { - prev = peerkey; - peerkey = peerkey->next; - os_free(prev); - } - } -#endif /* CONFIG_PEERKEY */ - 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) -{ - if (sm == NULL) - return; - - wpa_printf(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); -} - - -/** - * 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++; -} - - -/** - * 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); -} - - -/** - * 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 wpa_ssid *config) -{ - if (sm) { - sm->cur_ssid = config; - 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 */ - 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 */ - 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_printf(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_printf(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_printf(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 || sm->assoc_wpa_ie == NULL) { - wpa_printf(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; -} diff --git a/contrib/wpa_supplicant/wpa.h b/contrib/wpa_supplicant/wpa.h deleted file mode 100644 index 8a9ae7694ad6..000000000000 --- a/contrib/wpa_supplicant/wpa.h +++ /dev/null @@ -1,288 +0,0 @@ -/* - * wpa_supplicant - WPA definitions - * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "defs.h" -#include "wpa_common.h" - -#ifndef BIT -#define BIT(n) (1 << (n)) -#endif - -#define WPA_CAPABILITY_PREAUTH BIT(0) -#define WPA_CAPABILITY_MGMT_FRAME_PROTECTION BIT(6) -#define WPA_CAPABILITY_PEERKEY_ENABLED BIT(9) - -#define GENERIC_INFO_ELEM 0xdd -#define RSN_INFO_ELEM 0x30 - -enum { - REASON_UNSPECIFIED = 1, - REASON_DEAUTH_LEAVING = 3, - REASON_INVALID_IE = 13, - REASON_MICHAEL_MIC_FAILURE = 14, - REASON_4WAY_HANDSHAKE_TIMEOUT = 15, - REASON_GROUP_KEY_UPDATE_TIMEOUT = 16, - REASON_IE_IN_4WAY_DIFFERS = 17, - REASON_GROUP_CIPHER_NOT_VALID = 18, - REASON_PAIRWISE_CIPHER_NOT_VALID = 19, - REASON_AKMP_NOT_VALID = 20, - REASON_UNSUPPORTED_RSN_IE_VERSION = 21, - REASON_INVALID_RSN_IE_CAPAB = 22, - REASON_IEEE_802_1X_AUTH_FAILED = 23, - REASON_CIPHER_SUITE_REJECTED = 24 -}; - -#define PMKID_LEN 16 - - -struct wpa_sm; -struct wpa_ssid; -struct eapol_sm; -struct wpa_config_blob; - -struct wpa_sm_ctx { - void *ctx; /* pointer to arbitrary upper level context */ - - void (*set_state)(void *ctx, wpa_states state); - 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, 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 (*scan)(void *eloop_ctx, void *timeout_ctx); - struct wpa_ssid * (*get_ssid)(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); -}; - - -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 -}; - -struct wpa_ie_data { - int proto; - int pairwise_cipher; - int group_cipher; - int key_mgmt; - int capabilities; - int num_pmkid; - const u8 *pmkid; - int mgmt_group_cipher; -}; - -#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 wpa_ssid *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_sm_stkstart(struct wpa_sm *sm, const u8 *peer); - -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); - -#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 wpa_ssid *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_sm_stkstart(struct wpa_sm *sm, const u8 *peer) -{ - return -1; -} - -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; -} - -#endif /* CONFIG_NO_WPA */ - -#endif /* WPA_H */ diff --git a/contrib/wpa_supplicant/wpa_cli.c b/contrib/wpa_supplicant/wpa_cli.c deleted file mode 100644 index 6c3a8818245a..000000000000 --- a/contrib/wpa_supplicant/wpa_cli.c +++ /dev/null @@ -1,1643 +0,0 @@ -/* - * WPA Supplicant - command line interface for wpa_supplicant daemon - * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 <dirent.h> -#endif /* CONFIG_CTRL_IFACE_UNIX */ -#ifdef CONFIG_READLINE -#include <readline/readline.h> -#include <readline/history.h> -#endif /* CONFIG_READLINE */ - -#include "wpa_ctrl.h" -#include "common.h" -#include "version.h" - - -static const char *wpa_cli_version = -"wpa_cli v" VERSION_STR "\n" -"Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> and contributors"; - - -static const char *wpa_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 *wpa_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" -" status [verbose] = get current WPA/EAPOL/EAP status\n" -" mib = get MIB variables (dot1x, dot11)\n" -" help = show this usage help\n" -" interface [ifname] = show interfaces/select interface\n" -" level <debug level> = change debug level\n" -" license = show full wpa_cli license\n" -" logoff = IEEE 802.1X EAPOL state machine logoff\n" -" logon = IEEE 802.1X EAPOL state machine logon\n" -" set = set variables (shows list of variables when run without arguments)\n" -" pmksa = show PMKSA cache\n" -" reassociate = force reassociation\n" -" reconfigure = force wpa_supplicant to re-read its configuration file\n" -" preauthenticate <BSSID> = force preauthentication\n" -" identity <network id> <identity> = configure identity for an SSID\n" -" password <network id> <password> = configure password for an SSID\n" -" new_password <network id> <password> = change password for an SSID\n" -" pin <network id> <pin> = configure pin for an SSID\n" -" otp <network id> <password> = configure one-time-password for an SSID\n" -" passphrase <network id> <passphrase> = configure private key passphrase\n" -" for an SSID\n" -" bssid <network id> <BSSID> = set preferred BSSID for an SSID\n" -" list_networks = list configured networks\n" -" select_network <network id> = select a network (disable others)\n" -" enable_network <network id> = enable a network\n" -" disable_network <network id> = disable a network\n" -" add_network = add a network\n" -" remove_network <network id> = remove a network\n" -" set_network <network id> <variable> <value> = set network variables " -"(shows\n" -" list of variables when run without arguments)\n" -" get_network <network id> <variable> = get network variables\n" -" save_config = save the current configuration\n" -" disconnect = disconnect and wait for reassociate/reconnect command before\n " -" connecting\n" -" reconnect = like reassociate, but only takes effect if already " -"disconnected\n" -" scan = request new BSS scan\n" -" scan_results = get latest scan results\n" -" get_capability <eap/pairwise/group/key_mgmt/proto/auth_alg> = " -"get capabilies\n" -" ap_scan <value> = set ap_scan parameter\n" -" stkstart <addr> = request STK negotiation with <addr>\n" -" terminate = terminate wpa_supplicant\n" -" quit = exit wpa_cli\n"; - -static struct wpa_ctrl *ctrl_conn; -static int wpa_cli_quit = 0; -static int wpa_cli_attached = 0; -static int wpa_cli_connected = 0; -static int wpa_cli_last_id = 0; -static const char *ctrl_iface_dir = "/var/run/wpa_supplicant"; -static char *ctrl_ifname = NULL; -static const char *pid_file = NULL; -static const char *action_file = NULL; - - -static void usage(void) -{ - printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] " - "[-a<action file>] \\\n" - " [-P<pid file>] [-g<global ctrl>] [command..]\n" - " -h = help (show this usage text)\n" - " -v = shown version information\n" - " -a = run in daemon mode executing the action file based on " - "events from\n" - " wpa_supplicant\n" - " -B = run a daemon in the background\n" - " default path: /var/run/wpa_supplicant\n" - " default interface: first interface found in socket path\n" - "%s", - commands_help); -} - - -static struct wpa_ctrl * wpa_cli_open_connection(const char *ifname) -{ -#if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE) - ctrl_conn = wpa_ctrl_open(ifname); - return ctrl_conn; -#else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */ - char *cfile; - int flen; - - if (ifname == NULL) - return NULL; - - flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2; - cfile = os_malloc(flen); - if (cfile == NULL) - return NULL; - os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname); - - ctrl_conn = wpa_ctrl_open(cfile); - os_free(cfile); - return ctrl_conn; -#endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */ -} - - -static void wpa_cli_close_connection(void) -{ - if (ctrl_conn == NULL) - return; - - if (wpa_cli_attached) { - wpa_ctrl_detach(ctrl_conn); - wpa_cli_attached = 0; - } - wpa_ctrl_close(ctrl_conn); - ctrl_conn = NULL; -} - - -static void wpa_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[2048]; - size_t len; - int ret; - - if (ctrl_conn == NULL) { - printf("Not connected to wpa_supplicant - command dropped.\n"); - return -1; - } - len = sizeof(buf) - 1; - ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, - wpa_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 int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd) -{ - return _wpa_ctrl_command(ctrl, cmd, 1); -} - - -static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - int verbose = argc > 0 && os_strcmp(argv[0], "verbose") == 0; - return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS"); -} - - -static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_ctrl_command(ctrl, "PING"); -} - - -static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_ctrl_command(ctrl, "MIB"); -} - - -static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_ctrl_command(ctrl, "PMKSA"); -} - - -static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - printf("%s", commands_help); - return 0; -} - - -static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license); - return 0; -} - - -static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - wpa_cli_quit = 1; - return 0; -} - - -static void wpa_cli_show_variables(void) -{ - printf("set variables:\n" - " EAPOL::heldPeriod (EAPOL state machine held period, " - "in seconds)\n" - " EAPOL::authPeriod (EAPOL state machine authentication " - "period, in seconds)\n" - " EAPOL::startPeriod (EAPOL state machine start period, in " - "seconds)\n" - " EAPOL::maxStart (EAPOL state machine maximum start " - "attempts)\n"); - printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in " - "seconds)\n" - " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication" - " threshold\n\tpercentage)\n" - " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing " - "security\n\tassociation in seconds)\n"); -} - - -static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - char cmd[256]; - int res; - - if (argc == 0) { - wpa_cli_show_variables(); - return 0; - } - - 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 wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_ctrl_command(ctrl, "LOGOFF"); -} - - -static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_ctrl_command(ctrl, "LOGON"); -} - - -static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "REASSOCIATE"); -} - - -static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char cmd[256]; - int res; - - if (argc != 1) { - printf("Invalid PREAUTH command: needs one argument " - "(BSSID)\n"); - return -1; - } - - res = os_snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]); - if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { - printf("Too long PREAUTH command.\n"); - return -1; - } - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - char cmd[256]; - int res; - - if (argc != 1) { - printf("Invalid AP_SCAN command: needs one argument (ap_scan " - "value)\n"); - return -1; - } - res = os_snprintf(cmd, sizeof(cmd), "AP_SCAN %s", argv[0]); - if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { - printf("Too long AP_SCAN command.\n"); - return -1; - } - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char cmd[256]; - int res; - - if (argc != 1) { - printf("Invalid STKSTART command: needs one argument " - "(Peer STA MAC address)\n"); - return -1; - } - - res = os_snprintf(cmd, sizeof(cmd), "STKSTART %s", argv[0]); - if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { - printf("Too long STKSTART command.\n"); - return -1; - } - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - char cmd[256]; - int res; - - if (argc != 1) { - printf("Invalid LEVEL command: needs one argument (debug " - "level)\n"); - return -1; - } - res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]); - if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { - printf("Too long LEVEL command.\n"); - return -1; - } - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - char cmd[256], *pos, *end; - int i, ret; - - if (argc < 2) { - printf("Invalid IDENTITY command: needs two arguments " - "(network id and identity)\n"); - return -1; - } - - end = cmd + sizeof(cmd); - pos = cmd; - ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s", - argv[0], argv[1]); - if (ret < 0 || ret >= end - pos) { - printf("Too long IDENTITY command.\n"); - return -1; - } - pos += ret; - for (i = 2; i < argc; i++) { - ret = os_snprintf(pos, end - pos, " %s", argv[i]); - if (ret < 0 || ret >= end - pos) { - printf("Too long IDENTITY command.\n"); - return -1; - } - pos += ret; - } - - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - char cmd[256], *pos, *end; - int i, ret; - - if (argc < 2) { - printf("Invalid PASSWORD command: needs two arguments " - "(network id and password)\n"); - return -1; - } - - end = cmd + sizeof(cmd); - pos = cmd; - ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s", - argv[0], argv[1]); - if (ret < 0 || ret >= end - pos) { - printf("Too long PASSWORD command.\n"); - return -1; - } - pos += ret; - for (i = 2; i < argc; i++) { - ret = os_snprintf(pos, end - pos, " %s", argv[i]); - if (ret < 0 || ret >= end - pos) { - printf("Too long PASSWORD command.\n"); - return -1; - } - pos += ret; - } - - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char cmd[256], *pos, *end; - int i, ret; - - if (argc < 2) { - printf("Invalid NEW_PASSWORD command: needs two arguments " - "(network id and password)\n"); - return -1; - } - - end = cmd + sizeof(cmd); - pos = cmd; - ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s", - argv[0], argv[1]); - if (ret < 0 || ret >= end - pos) { - printf("Too long NEW_PASSWORD command.\n"); - return -1; - } - pos += ret; - for (i = 2; i < argc; i++) { - ret = os_snprintf(pos, end - pos, " %s", argv[i]); - if (ret < 0 || ret >= end - pos) { - printf("Too long NEW_PASSWORD command.\n"); - return -1; - } - pos += ret; - } - - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - char cmd[256], *pos, *end; - int i, ret; - - if (argc < 2) { - printf("Invalid PIN command: needs two arguments " - "(network id and pin)\n"); - return -1; - } - - end = cmd + sizeof(cmd); - pos = cmd; - ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s", - argv[0], argv[1]); - if (ret < 0 || ret >= end - pos) { - printf("Too long PIN command.\n"); - return -1; - } - pos += ret; - for (i = 2; i < argc; i++) { - ret = os_snprintf(pos, end - pos, " %s", argv[i]); - if (ret < 0 || ret >= end - pos) { - printf("Too long PIN command.\n"); - return -1; - } - pos += ret; - } - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - char cmd[256], *pos, *end; - int i, ret; - - if (argc < 2) { - printf("Invalid OTP command: needs two arguments (network " - "id and password)\n"); - return -1; - } - - end = cmd + sizeof(cmd); - pos = cmd; - ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s", - argv[0], argv[1]); - if (ret < 0 || ret >= end - pos) { - printf("Too long OTP command.\n"); - return -1; - } - pos += ret; - for (i = 2; i < argc; i++) { - ret = os_snprintf(pos, end - pos, " %s", argv[i]); - if (ret < 0 || ret >= end - pos) { - printf("Too long OTP command.\n"); - return -1; - } - pos += ret; - } - - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char cmd[256], *pos, *end; - int i, ret; - - if (argc < 2) { - printf("Invalid PASSPHRASE command: needs two arguments " - "(network id and passphrase)\n"); - return -1; - } - - end = cmd + sizeof(cmd); - pos = cmd; - ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s", - argv[0], argv[1]); - if (ret < 0 || ret >= end - pos) { - printf("Too long PASSPHRASE command.\n"); - return -1; - } - pos += ret; - for (i = 2; i < argc; i++) { - ret = os_snprintf(pos, end - pos, " %s", argv[i]); - if (ret < 0 || ret >= end - pos) { - printf("Too long PASSPHRASE command.\n"); - return -1; - } - pos += ret; - } - - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - char cmd[256], *pos, *end; - int i, ret; - - if (argc < 2) { - printf("Invalid BSSID command: needs two arguments (network " - "id and BSSID)\n"); - return -1; - } - - end = cmd + sizeof(cmd); - pos = cmd; - ret = os_snprintf(pos, end - pos, "BSSID"); - if (ret < 0 || ret >= end - pos) { - printf("Too long BSSID command.\n"); - return -1; - } - pos += ret; - for (i = 0; i < argc; i++) { - ret = os_snprintf(pos, end - pos, " %s", argv[i]); - if (ret < 0 || ret >= end - pos) { - printf("Too long BSSID command.\n"); - return -1; - } - pos += ret; - } - - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "LIST_NETWORKS"); -} - - -static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char cmd[32]; - - if (argc < 1) { - printf("Invalid SELECT_NETWORK command: needs one argument " - "(network id)\n"); - return -1; - } - - os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]); - cmd[sizeof(cmd) - 1] = '\0'; - - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char cmd[32]; - - if (argc < 1) { - printf("Invalid ENABLE_NETWORK command: needs one argument " - "(network id)\n"); - return -1; - } - - os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]); - cmd[sizeof(cmd) - 1] = '\0'; - - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char cmd[32]; - - if (argc < 1) { - printf("Invalid DISABLE_NETWORK command: needs one argument " - "(network id)\n"); - return -1; - } - - os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]); - cmd[sizeof(cmd) - 1] = '\0'; - - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "ADD_NETWORK"); -} - - -static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char cmd[32]; - - if (argc < 1) { - printf("Invalid REMOVE_NETWORK command: needs one argument " - "(network id)\n"); - return -1; - } - - os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]); - cmd[sizeof(cmd) - 1] = '\0'; - - return wpa_ctrl_command(ctrl, cmd); -} - - -static void wpa_cli_show_network_variables(void) -{ - printf("set_network variables:\n" - " ssid (network name, SSID)\n" - " psk (WPA passphrase or pre-shared key)\n" - " key_mgmt (key management protocol)\n" - " identity (EAP identity)\n" - " password (EAP password)\n" - " ...\n" - "\n" - "Note: Values are entered in the same format as the " - "configuration file is using,\n" - "i.e., strings values need to be inside double quotation " - "marks.\n" - "For example: set_network 1 ssid \"network name\"\n" - "\n" - "Please see wpa_supplicant.conf documentation for full list " - "of\navailable variables.\n"); -} - - -static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char cmd[256]; - int res; - - if (argc == 0) { - wpa_cli_show_network_variables(); - return 0; - } - - if (argc != 3) { - printf("Invalid SET_NETWORK command: needs three arguments\n" - "(network id, variable name, and value)\n"); - return -1; - } - - res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s", - argv[0], argv[1], argv[2]); - if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { - printf("Too long SET_NETWORK command.\n"); - return -1; - } - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char cmd[256]; - int res; - - if (argc == 0) { - wpa_cli_show_network_variables(); - return 0; - } - - if (argc != 2) { - printf("Invalid GET_NETWORK command: needs two arguments\n" - "(network id and variable name)\n"); - return -1; - } - - res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s", - argv[0], argv[1]); - if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { - printf("Too long GET_NETWORK command.\n"); - return -1; - } - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "DISCONNECT"); -} - - -static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "RECONNECT"); -} - - -static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "SAVE_CONFIG"); -} - - -static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - return wpa_ctrl_command(ctrl, "SCAN"); -} - - -static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "SCAN_RESULTS"); -} - - -static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char cmd[64]; - - if (argc < 1 || argc > 2) { - printf("Invalid GET_CAPABILITY command: need either one or " - "two arguments\n"); - return -1; - } - - if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) { - printf("Invalid GET_CAPABILITY command: second argument, " - "if any, must be 'strict'\n"); - return -1; - } - - os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0], - (argc == 2) ? " strict" : ""); - cmd[sizeof(cmd) - 1] = '\0'; - - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl) -{ - printf("Available interfaces:\n"); - return wpa_ctrl_command(ctrl, "INTERFACES"); -} - - -static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - if (argc < 1) { - wpa_cli_list_interfaces(ctrl); - return 0; - } - - wpa_cli_close_connection(); - os_free(ctrl_ifname); - ctrl_ifname = os_strdup(argv[0]); - - if (wpa_cli_open_connection(ctrl_ifname)) { - printf("Connected to interface '%s.\n", ctrl_ifname); - if (wpa_ctrl_attach(ctrl_conn) == 0) { - wpa_cli_attached = 1; - } else { - printf("Warning: Failed to attach to " - "wpa_supplicant.\n"); - } - } else { - printf("Could not connect to interface '%s' - re-trying\n", - ctrl_ifname); - } - return 0; -} - - -static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "RECONFIGURE"); -} - - -static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - return wpa_ctrl_command(ctrl, "TERMINATE"); -} - - -static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char cmd[256]; - - if (argc < 1) { - printf("Invalid INTERFACE_ADD command: needs at least one " - "argument (interface name)\n" - "All arguments: ifname confname driver ctrl_interface " - "driver_param bridge_name\n"); - return -1; - } - - /* - * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB - * <driver_param>TAB<bridge_name> - */ - os_snprintf(cmd, sizeof(cmd), "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s", - argv[0], - argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "", - argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "", - argc > 5 ? argv[5] : ""); - cmd[sizeof(cmd) - 1] = '\0'; - return wpa_ctrl_command(ctrl, cmd); -} - - -static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc, - char *argv[]) -{ - char cmd[128]; - - if (argc != 1) { - printf("Invalid INTERFACE_REMOVE command: needs one argument " - "(interface name)\n"); - return -1; - } - - os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]); - cmd[sizeof(cmd) - 1] = '\0'; - return wpa_ctrl_command(ctrl, cmd); -} - - -struct wpa_cli_cmd { - const char *cmd; - int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]); -}; - -static struct wpa_cli_cmd wpa_cli_commands[] = { - { "status", wpa_cli_cmd_status }, - { "ping", wpa_cli_cmd_ping }, - { "mib", wpa_cli_cmd_mib }, - { "help", wpa_cli_cmd_help }, - { "interface", wpa_cli_cmd_interface }, - { "level", wpa_cli_cmd_level }, - { "license", wpa_cli_cmd_license }, - { "quit", wpa_cli_cmd_quit }, - { "set", wpa_cli_cmd_set }, - { "logon", wpa_cli_cmd_logon }, - { "logoff", wpa_cli_cmd_logoff }, - { "pmksa", wpa_cli_cmd_pmksa }, - { "reassociate", wpa_cli_cmd_reassociate }, - { "preauthenticate", wpa_cli_cmd_preauthenticate }, - { "identity", wpa_cli_cmd_identity }, - { "password", wpa_cli_cmd_password }, - { "new_password", wpa_cli_cmd_new_password }, - { "pin", wpa_cli_cmd_pin }, - { "otp", wpa_cli_cmd_otp }, - { "passphrase", wpa_cli_cmd_passphrase }, - { "bssid", wpa_cli_cmd_bssid }, - { "list_networks", wpa_cli_cmd_list_networks }, - { "select_network", wpa_cli_cmd_select_network }, - { "enable_network", wpa_cli_cmd_enable_network }, - { "disable_network", wpa_cli_cmd_disable_network }, - { "add_network", wpa_cli_cmd_add_network }, - { "remove_network", wpa_cli_cmd_remove_network }, - { "set_network", wpa_cli_cmd_set_network }, - { "get_network", wpa_cli_cmd_get_network }, - { "save_config", wpa_cli_cmd_save_config }, - { "disconnect", wpa_cli_cmd_disconnect }, - { "reconnect", wpa_cli_cmd_reconnect }, - { "scan", wpa_cli_cmd_scan }, - { "scan_results", wpa_cli_cmd_scan_results }, - { "get_capability", wpa_cli_cmd_get_capability }, - { "reconfigure", wpa_cli_cmd_reconfigure }, - { "terminate", wpa_cli_cmd_terminate }, - { "interface_add", wpa_cli_cmd_interface_add }, - { "interface_remove", wpa_cli_cmd_interface_remove }, - { "ap_scan", wpa_cli_cmd_ap_scan }, - { "stkstart", wpa_cli_cmd_stkstart }, - { NULL, NULL } -}; - - -static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[]) -{ - struct wpa_cli_cmd *cmd, *match = NULL; - int count; - int ret = 0; - - count = 0; - cmd = wpa_cli_commands; - while (cmd->cmd) { - if (os_strncasecmp(cmd->cmd, argv[0], os_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 = wpa_cli_commands; - while (cmd->cmd) { - if (os_strncasecmp(cmd->cmd, argv[0], - os_strlen(argv[0])) == 0) { - printf(" %s", cmd->cmd); - } - cmd++; - } - printf("\n"); - ret = 1; - } else if (count == 0) { - printf("Unknown command '%s'\n", argv[0]); - ret = 1; - } else { - ret = match->handler(ctrl, argc - 1, &argv[1]); - } - - return ret; -} - - -static int str_match(const char *a, const char *b) -{ - return os_strncmp(a, b, os_strlen(b)) == 0; -} - - -static int wpa_cli_exec(const char *program, const char *arg1, - const char *arg2) -{ - char *cmd; - size_t len; - int ret = 0; - - len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3; - cmd = os_malloc(len); - if (cmd == NULL) - return -1; - os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2); - cmd[len - 1] = '\0'; -#ifndef _WIN32_WCE - if (system(cmd) < 0) - ret = -1; -#endif /* _WIN32_WCE */ - os_free(cmd); - - return ret; -} - - -static void wpa_cli_action_process(const char *msg) -{ - const char *pos; - char *copy = NULL, *id, *pos2; - - pos = msg; - if (*pos == '<') { - /* skip priority */ - pos = os_strchr(pos, '>'); - if (pos) - pos++; - else - pos = msg; - } - - if (str_match(pos, WPA_EVENT_CONNECTED)) { - int new_id = -1; - os_unsetenv("WPA_ID"); - os_unsetenv("WPA_ID_STR"); - os_unsetenv("WPA_CTRL_DIR"); - - pos = os_strstr(pos, "[id="); - if (pos) - copy = os_strdup(pos + 4); - - if (copy) { - pos2 = id = copy; - while (*pos2 && *pos2 != ' ') - pos2++; - *pos2++ = '\0'; - new_id = atoi(id); - os_setenv("WPA_ID", id, 1); - while (*pos2 && *pos2 != '=') - pos2++; - if (*pos2 == '=') - pos2++; - id = pos2; - while (*pos2 && *pos2 != ']') - pos2++; - *pos2 = '\0'; - os_setenv("WPA_ID_STR", id, 1); - os_free(copy); - } - - os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1); - - if (!wpa_cli_connected || new_id != wpa_cli_last_id) { - wpa_cli_connected = 1; - wpa_cli_last_id = new_id; - wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED"); - } - } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) { - if (wpa_cli_connected) { - wpa_cli_connected = 0; - wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED"); - } - } else if (str_match(pos, WPA_EVENT_TERMINATING)) { - printf("wpa_supplicant is terminating - stop monitoring\n"); - wpa_cli_quit = 1; - } -} - - -#ifndef CONFIG_ANSI_C_EXTRA -static void wpa_cli_action_cb(char *msg, size_t len) -{ - wpa_cli_action_process(msg); -} -#endif /* CONFIG_ANSI_C_EXTRA */ - - -static void wpa_cli_reconnect(void) -{ - wpa_cli_close_connection(); - ctrl_conn = wpa_cli_open_connection(ctrl_ifname); - if (ctrl_conn) { - printf("Connection to wpa_supplicant re-established\n"); - if (wpa_ctrl_attach(ctrl_conn) == 0) { - wpa_cli_attached = 1; - } else { - printf("Warning: Failed to attach to " - "wpa_supplicant.\n"); - } - } -} - - -static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read, - int action_monitor) -{ - int first = 1; - if (ctrl_conn == NULL) { - wpa_cli_reconnect(); - return; - } - while (wpa_ctrl_pending(ctrl) > 0) { - char buf[256]; - size_t len = sizeof(buf) - 1; - if (wpa_ctrl_recv(ctrl, buf, &len) == 0) { - buf[len] = '\0'; - if (action_monitor) - wpa_cli_action_process(buf); - else { - if (in_read && first) - printf("\n"); - first = 0; - printf("%s\n", buf); - } - } else { - printf("Could not read pending message.\n"); - break; - } - } - - if (wpa_ctrl_pending(ctrl) < 0) { - printf("Connection to wpa_supplicant lost - trying to " - "reconnect\n"); - wpa_cli_reconnect(); - } -} - - -#ifdef CONFIG_READLINE -static char * wpa_cli_cmd_gen(const char *text, int state) -{ - static int i, len; - const char *cmd; - - if (state == 0) { - i = 0; - len = os_strlen(text); - } - - while ((cmd = wpa_cli_commands[i].cmd)) { - i++; - if (os_strncasecmp(cmd, text, len) == 0) - return os_strdup(cmd); - } - - return NULL; -} - - -static char * wpa_cli_dummy_gen(const char *text, int state) -{ - return NULL; -} - - -static char ** wpa_cli_completion(const char *text, int start, int end) -{ - return rl_completion_matches(text, start == 0 ? - wpa_cli_cmd_gen : wpa_cli_dummy_gen); -} -#endif /* CONFIG_READLINE */ - - -static void wpa_cli_interactive(void) -{ -#define max_args 10 - char cmdbuf[256], *cmd, *argv[max_args], *pos; - int argc; -#ifdef CONFIG_READLINE - char *home, *hfile = NULL; -#endif /* CONFIG_READLINE */ - - printf("\nInteractive mode\n\n"); - -#ifdef CONFIG_READLINE - rl_attempted_completion_function = wpa_cli_completion; - home = getenv("HOME"); - if (home) { - const char *fname = ".wpa_cli_history"; - int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1; - hfile = os_malloc(hfile_len); - if (hfile) { - os_snprintf(hfile, hfile_len, "%s/%s", home, fname); - hfile[hfile_len - 1] = '\0'; - read_history(hfile); - stifle_history(100); - } - } -#endif /* CONFIG_READLINE */ - - do { - wpa_cli_recv_pending(ctrl_conn, 0, 0); -#ifndef CONFIG_NATIVE_WINDOWS - alarm(1); -#endif /* CONFIG_NATIVE_WINDOWS */ -#ifdef CONFIG_READLINE - cmd = readline("> "); - 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(); - } -#else /* CONFIG_READLINE */ - printf("> "); - cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin); -#endif /* CONFIG_READLINE */ -#ifndef CONFIG_NATIVE_WINDOWS - alarm(0); -#endif /* CONFIG_NATIVE_WINDOWS */ - if (cmd == NULL) - break; - wpa_cli_recv_pending(ctrl_conn, 0, 0); - 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; - if (*pos == '"') { - char *pos2 = os_strrchr(pos, '"'); - if (pos2) - pos = pos2 + 1; - } - while (*pos != '\0' && *pos != ' ') - pos++; - if (*pos == ' ') - *pos++ = '\0'; - } - if (argc) - wpa_request(ctrl_conn, argc, argv); - - if (cmd != cmdbuf) - os_free(cmd); - } while (!wpa_cli_quit); - -#ifdef CONFIG_READLINE - if (hfile) { - /* Save command history, excluding lines that may contain - * passwords. */ - HIST_ENTRY *h; - history_set_pos(0); - h = next_history(); - while (h) { - char *p = h->line; - while (*p == ' ' || *p == '\t') - p++; - if (os_strncasecmp(p, "pa", 2) == 0 || - os_strncasecmp(p, "o", 1) == 0 || - os_strncasecmp(p, "n", 1)) { - h = remove_history(where_history()); - if (h) { - os_free(h->line); - os_free(h->data); - os_free(h); - } - h = current_history(); - } else { - h = next_history(); - } - } - write_history(hfile); - os_free(hfile); - } -#endif /* CONFIG_READLINE */ -} - - -static void wpa_cli_action(struct wpa_ctrl *ctrl) -{ -#ifdef CONFIG_ANSI_C_EXTRA - /* TODO: ANSI C version(?) */ - printf("Action processing not supported in ANSI C build.\n"); -#else /* CONFIG_ANSI_C_EXTRA */ - fd_set rfds; - int fd, res; - struct timeval tv; - char buf[256]; /* note: large enough to fit in unsolicited messages */ - size_t len; - - fd = wpa_ctrl_get_fd(ctrl); - - while (!wpa_cli_quit) { - FD_ZERO(&rfds); - FD_SET(fd, &rfds); - tv.tv_sec = 2; - 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)) - wpa_cli_recv_pending(ctrl, 0, 1); - else { - /* verify that connection is still working */ - len = sizeof(buf) - 1; - if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len, - wpa_cli_action_cb) < 0 || - len < 4 || os_memcmp(buf, "PONG", 4) != 0) { - printf("wpa_supplicant did not reply to PING " - "command - exiting\n"); - break; - } - } - } -#endif /* CONFIG_ANSI_C_EXTRA */ -} - - -static void wpa_cli_cleanup(void) -{ - wpa_cli_close_connection(); - if (pid_file) - os_daemonize_terminate(pid_file); - - os_program_deinit(); -} - -static void wpa_cli_terminate(int sig) -{ - wpa_cli_cleanup(); - exit(0); -} - - -#ifndef CONFIG_NATIVE_WINDOWS -static void wpa_cli_alarm(int sig) -{ - if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) { - printf("Connection to wpa_supplicant lost - trying to " - "reconnect\n"); - wpa_cli_close_connection(); - } - if (!ctrl_conn) - wpa_cli_reconnect(); - if (ctrl_conn) - wpa_cli_recv_pending(ctrl_conn, 1, 0); - alarm(1); -} -#endif /* CONFIG_NATIVE_WINDOWS */ - - -static char * wpa_cli_get_default_ifname(void) -{ - char *ifname = NULL; - -#ifdef CONFIG_CTRL_IFACE_UNIX - struct dirent *dent; - DIR *dir = opendir(ctrl_iface_dir); - if (!dir) - return NULL; - 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; - printf("Selected interface '%s'\n", dent->d_name); - ifname = os_strdup(dent->d_name); - break; - } - closedir(dir); -#endif /* CONFIG_CTRL_IFACE_UNIX */ - -#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE - char buf[2048], *pos; - size_t len; - struct wpa_ctrl *ctrl; - int ret; - - ctrl = wpa_ctrl_open(NULL); - if (ctrl == NULL) - return NULL; - - len = sizeof(buf) - 1; - ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL); - if (ret >= 0) { - buf[len] = '\0'; - pos = os_strchr(buf, '\n'); - if (pos) - *pos = '\0'; - ifname = os_strdup(buf); - } - wpa_ctrl_close(ctrl); -#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ - - return ifname; -} - - -int main(int argc, char *argv[]) -{ - int interactive; - int warning_displayed = 0; - int c; - int daemonize = 0; - int ret = 0; - const char *global = NULL; - - if (os_program_init()) - return -1; - - for (;;) { - c = getopt(argc, argv, "a:Bg:hi:p:P:v"); - if (c < 0) - break; - switch (c) { - case 'a': - action_file = optarg; - break; - case 'B': - daemonize = 1; - break; - case 'g': - global = optarg; - break; - case 'h': - usage(); - return 0; - case 'v': - printf("%s\n", wpa_cli_version); - return 0; - case 'i': - os_free(ctrl_ifname); - ctrl_ifname = os_strdup(optarg); - break; - case 'p': - ctrl_iface_dir = optarg; - break; - case 'P': - pid_file = optarg; - break; - default: - usage(); - return -1; - } - } - - interactive = (argc == optind) && (action_file == NULL); - - if (interactive) - printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license); - - if (global) { -#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE - ctrl_conn = wpa_ctrl_open(NULL); -#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */ - ctrl_conn = wpa_ctrl_open(global); -#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ - if (ctrl_conn == NULL) { - perror("Failed to connect to wpa_supplicant - " - "wpa_ctrl_open"); - return -1; - } - } - - for (; !global;) { - if (ctrl_ifname == NULL) - ctrl_ifname = wpa_cli_get_default_ifname(); - ctrl_conn = wpa_cli_open_connection(ctrl_ifname); - if (ctrl_conn) { - if (warning_displayed) - printf("Connection established.\n"); - break; - } - - if (!interactive) { - perror("Failed to connect to wpa_supplicant - " - "wpa_ctrl_open"); - return -1; - } - - if (!warning_displayed) { - printf("Could not connect to wpa_supplicant - " - "re-trying\n"); - warning_displayed = 1; - } - os_sleep(1, 0); - continue; - } - -#ifndef _WIN32_WCE - signal(SIGINT, wpa_cli_terminate); - signal(SIGTERM, wpa_cli_terminate); -#endif /* _WIN32_WCE */ -#ifndef CONFIG_NATIVE_WINDOWS - signal(SIGALRM, wpa_cli_alarm); -#endif /* CONFIG_NATIVE_WINDOWS */ - - if (interactive || action_file) { - if (wpa_ctrl_attach(ctrl_conn) == 0) { - wpa_cli_attached = 1; - } else { - printf("Warning: Failed to attach to " - "wpa_supplicant.\n"); - if (!interactive) - return -1; - } - } - - if (daemonize && os_daemonize(pid_file)) - return -1; - - if (interactive) - wpa_cli_interactive(); - else if (action_file) - wpa_cli_action(ctrl_conn); - else - ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]); - - os_free(ctrl_ifname); - wpa_cli_cleanup(); - - return ret; -} - -#else /* CONFIG_CTRL_IFACE */ -int main(int argc, char *argv[]) -{ - printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n"); - return -1; -} -#endif /* CONFIG_CTRL_IFACE */ diff --git a/contrib/wpa_supplicant/wpa_common.h b/contrib/wpa_supplicant/wpa_common.h deleted file mode 100644 index 6d0316ce4a38..000000000000 --- a/contrib/wpa_supplicant/wpa_common.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * WPA definitions shared between hostapd and wpa_supplicant - * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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_REPLAY_COUNTER_LEN 8 -#define WPA_NONCE_LEN 32 -#define WPA_KEY_RSC_LEN 8 - - -/* IEEE Std 802.1X-2004 */ - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -struct ieee802_1x_hdr { - u8 version; - u8 type; - u16 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 }; - -#ifdef CONFIG_IEEE80211W -#define WPA_DGTK_LEN 16 -#define WPA_DHV_LEN 16 -#define WPA_IGTK_LEN 16 -#endif /* CONFIG_IEEE80211W */ - -#endif /* WPA_COMMON_H */ diff --git a/contrib/wpa_supplicant/wpa_ctrl.c b/contrib/wpa_supplicant/wpa_ctrl.c deleted file mode 100644 index 8e621b061715..000000000000 --- a/contrib/wpa_supplicant/wpa_ctrl.c +++ /dev/null @@ -1,427 +0,0 @@ -/* - * wpa_supplicant/hostapd control interface library - * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - * - * $FreeBSD$ - */ - -#include "includes.h" - -#ifdef CONFIG_CTRL_IFACE - -#ifdef CONFIG_CTRL_IFACE_UNIX -#include <sys/un.h> -#endif /* CONFIG_CTRL_IFACE_UNIX */ - -#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 - -struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path) -{ - struct wpa_ctrl *ctrl; - static int counter = 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; - os_snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path), - "/tmp/wpa_ctrl_%d-%d", getpid(), counter++); - if (bind(ctrl->s, (struct sockaddr *) &ctrl->local, - sizeof(ctrl->local)) < 0) { - close(ctrl->s); - os_free(ctrl); - return NULL; - } - - ctrl->dest.sun_family = AF_UNIX; - os_snprintf(ctrl->dest.sun_path, sizeof(ctrl->dest.sun_path), "%s", - ctrl_path); - 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) -{ - unlink(ctrl->local.sun_path); - 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 = 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 = strlen(ctrl->cookie) + 1 + cmd_len; - cmd_buf = os_malloc(_cmd_len ); - if (cmd_buf == NULL) - return -1; - _cmd = cmd_buf; - pos = cmd_buf; - strcpy(pos, ctrl->cookie); - pos += strlen(ctrl->cookie); - *pos++ = ' '; - 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 = 2; - tv.tv_usec = 0; - FD_ZERO(&rfds); - FD_SET(ctrl->s, &rfds); - res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv); - 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; - - ctrl = os_malloc(sizeof(*ctrl)); - if (ctrl == NULL) - return NULL; - os_memset(ctrl, 0, sizeof(*ctrl)); - -#ifdef UNICODE - if (ctrl_path == NULL) - _snwprintf(name, 256, NAMED_PIPE_PREFIX); - else - _snwprintf(name, 256, NAMED_PIPE_PREFIX TEXT("-%S"), - ctrl_path); -#else /* UNICODE */ - if (ctrl_path == NULL) - os_snprintf(name, 256, NAMED_PIPE_PREFIX); - else - os_snprintf(name, 256, NAMED_PIPE_PREFIX "-%s", - ctrl_path); -#endif /* UNICODE */ - - 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/contrib/wpa_supplicant/wpa_ctrl.h b/contrib/wpa_supplicant/wpa_ctrl.h deleted file mode 100644 index 6166fda26ee9..000000000000 --- a/contrib/wpa_supplicant/wpa_ctrl.h +++ /dev/null @@ -1,185 +0,0 @@ -/* - * wpa_supplicant/hostapd control interface library - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 " -/** 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 selected */ -#define WPA_EVENT_EAP_METHOD "CTRL-EVENT-EAP-METHOD " -/** 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 " - - -/* 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/contrib/wpa_supplicant/wpa_gui-qt4/eventhistory.cpp b/contrib/wpa_supplicant/wpa_gui-qt4/eventhistory.cpp deleted file mode 100644 index ebf3c9712d45..000000000000 --- a/contrib/wpa_supplicant/wpa_gui-qt4/eventhistory.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/* - * wpa_gui - EventHistory class - * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 <QHeaderView> - -#include "eventhistory.h" - - -int EventListModel::rowCount(const QModelIndex &) const -{ - return msgList.count(); -} - - -int EventListModel::columnCount(const QModelIndex &) const -{ - return 2; -} - - -QVariant EventListModel::data(const QModelIndex &index, int role) const -{ - if (!index.isValid()) - return QVariant(); - - if (role == Qt::DisplayRole) - if (index.column() == 0) { - if (index.row() >= timeList.size()) - return QVariant(); - return timeList.at(index.row()); - } else { - if (index.row() >= msgList.size()) - return QVariant(); - return msgList.at(index.row()); - } - else - return QVariant(); -} - - -QVariant EventListModel::headerData(int section, Qt::Orientation orientation, - int role) const -{ - if (role != Qt::DisplayRole) - return QVariant(); - - if (orientation == Qt::Horizontal) { - switch (section) { - case 0: - return QString("Timestamp"); - case 1: - return QString("Message"); - default: - return QVariant(); - } - } else - return QString("%1").arg(section); -} - - -void EventListModel::addEvent(QString time, QString msg) -{ - beginInsertRows(QModelIndex(), msgList.size(), msgList.size() + 1); - timeList << time; - msgList << msg; - endInsertRows(); -} - - -EventHistory::EventHistory(QWidget *parent, const char *, bool, Qt::WFlags) - : QDialog(parent) -{ - setupUi(this); - - connect(closeButton, SIGNAL(clicked()), this, SLOT(close())); - - elm = new EventListModel(parent); - eventListView->setModel(elm); -} - - -EventHistory::~EventHistory() -{ - destroy(); - delete elm; -} - - -void EventHistory::languageChange() -{ - retranslateUi(this); -} - - -void EventHistory::addEvents(WpaMsgList msgs) -{ - WpaMsgList::iterator it; - for (it = msgs.begin(); it != msgs.end(); it++) - addEvent(*it); -} - - -void EventHistory::addEvent(WpaMsg msg) -{ - elm->addEvent(msg.getTimestamp().toString("yyyy-MM-dd hh:mm:ss.zzz"), - msg.getMsg()); -#if QT_VERSION >= 0x040100 - eventListView->resizeColumnsToContents(); - eventListView->resizeRowsToContents(); -#endif -} diff --git a/contrib/wpa_supplicant/wpa_gui-qt4/eventhistory.h b/contrib/wpa_supplicant/wpa_gui-qt4/eventhistory.h deleted file mode 100644 index 40dff6d6d779..000000000000 --- a/contrib/wpa_supplicant/wpa_gui-qt4/eventhistory.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * wpa_gui - EventHistory class - * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 EVENTHISTORY_H -#define EVENTHISTORY_H - -#include <QObject> -#include "ui_eventhistory.h" - - -class EventListModel : public QAbstractTableModel -{ - Q_OBJECT - -public: - EventListModel(QObject *parent = 0) - : QAbstractTableModel(parent) {} - - int rowCount(const QModelIndex &parent = QModelIndex()) const; - int columnCount(const QModelIndex &parent = QModelIndex()) const; - QVariant data(const QModelIndex &index, int role) const; - QVariant headerData(int section, Qt::Orientation orientation, - int role = Qt::DisplayRole) const; - void addEvent(QString time, QString msg); - -private: - QStringList timeList; - QStringList msgList; -}; - - -class EventHistory : public QDialog, public Ui::EventHistory -{ - Q_OBJECT - -public: - EventHistory(QWidget *parent = 0, const char *name = 0, - bool modal = false, Qt::WFlags fl = 0); - ~EventHistory(); - -public slots: - virtual void addEvents(WpaMsgList msgs); - virtual void addEvent(WpaMsg msg); - -protected slots: - virtual void languageChange(); - -private: - EventListModel *elm; -}; - -#endif /* EVENTHISTORY_H */ diff --git a/contrib/wpa_supplicant/wpa_gui-qt4/eventhistory.ui b/contrib/wpa_supplicant/wpa_gui-qt4/eventhistory.ui deleted file mode 100644 index d47f461380a5..000000000000 --- a/contrib/wpa_supplicant/wpa_gui-qt4/eventhistory.ui +++ /dev/null @@ -1,93 +0,0 @@ -<ui version="4.0" stdsetdef="1" > - <author></author> - <comment></comment> - <exportmacro></exportmacro> - <class>EventHistory</class> - <widget class="QDialog" name="EventHistory" > - <property name="geometry" > - <rect> - <x>0</x> - <y>0</y> - <width>533</width> - <height>285</height> - </rect> - </property> - <property name="windowTitle" > - <string>Event history</string> - </property> - <layout class="QVBoxLayout" > - <item> - <widget class="QTableView" name="eventListView" > - <property name="sizePolicy" > - <sizepolicy> - <hsizetype>7</hsizetype> - <vsizetype>7</vsizetype> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="selectionMode" > - <enum>QAbstractItemView::NoSelection</enum> - </property> - <column> - <property name="text" > - <string>Timestamp</string> - </property> - <property name="clickable" > - <bool>true</bool> - </property> - <property name="resizable" > - <bool>true</bool> - </property> - </column> - <column> - <property name="text" > - <string>Message</string> - </property> - <property name="clickable" > - <bool>true</bool> - </property> - <property name="resizable" > - <bool>true</bool> - </property> - </column> - </widget> - </item> - <item> - <layout class="QHBoxLayout" > - <property name="margin" > - <number>0</number> - </property> - <item> - <spacer name="spacer3" > - <property name="sizeHint" > - <size> - <width>20</width> - <height>20</height> - </size> - </property> - <property name="sizeType" > - <enum>Expanding</enum> - </property> - <property name="orientation" > - <enum>Horizontal</enum> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="closeButton" > - <property name="text" > - <string>Close</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - <layoutdefault spacing="6" margin="11" /> - <pixmapfunction>qPixmapFromMimeSource</pixmapfunction> - <includes> - <include location="local" >wpamsg.h</include> - </includes> -</ui> diff --git a/contrib/wpa_supplicant/wpa_gui-qt4/main.cpp b/contrib/wpa_supplicant/wpa_gui-qt4/main.cpp deleted file mode 100644 index eeeda399d862..000000000000 --- a/contrib/wpa_supplicant/wpa_gui-qt4/main.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * wpa_gui - Application startup - * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 CONFIG_NATIVE_WINDOWS -#include <winsock.h> -#endif /* CONFIG_NATIVE_WINDOWS */ -#include <QApplication> -#include "wpagui.h" - -int main(int argc, char *argv[]) -{ - QApplication app(argc, argv); - WpaGui w; - int ret; - -#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 */ - - w.show(); - app.connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit())); - ret = app.exec(); - -#ifdef CONFIG_NATIVE_WINDOWS - WSACleanup(); -#endif /* CONFIG_NATIVE_WINDOWS */ - - return ret; -} diff --git a/contrib/wpa_supplicant/wpa_gui-qt4/networkconfig.cpp b/contrib/wpa_supplicant/wpa_gui-qt4/networkconfig.cpp deleted file mode 100644 index b8e17ac29403..000000000000 --- a/contrib/wpa_supplicant/wpa_gui-qt4/networkconfig.cpp +++ /dev/null @@ -1,583 +0,0 @@ -/* - * wpa_gui - NetworkConfig class - * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 <cstdio> -#include <QMessageBox> - -#include "networkconfig.h" -#include "wpagui.h" - -enum { - AUTH_NONE = 0, - AUTH_IEEE8021X = 1, - AUTH_WPA_PSK = 2, - AUTH_WPA_EAP = 3, - AUTH_WPA2_PSK = 4, - AUTH_WPA2_EAP = 5 -}; - -#define WPA_GUI_KEY_DATA "[key is configured]" - - -NetworkConfig::NetworkConfig(QWidget *parent, const char *, bool, Qt::WFlags) - : QDialog(parent) -{ - setupUi(this); - - connect(authSelect, SIGNAL(activated(int)), this, - SLOT(authChanged(int))); - connect(cancelButton, SIGNAL(clicked()), this, SLOT(close())); - connect(addButton, SIGNAL(clicked()), this, SLOT(addNetwork())); - connect(encrSelect, SIGNAL(activated(const QString &)), this, - SLOT(encrChanged(const QString &))); - connect(removeButton, SIGNAL(clicked()), this, SLOT(removeNetwork())); - - wpagui = NULL; - new_network = false; -} - - -NetworkConfig::~NetworkConfig() -{ -} - - -void NetworkConfig::languageChange() -{ - retranslateUi(this); -} - - -void NetworkConfig::paramsFromScanResults(Q3ListViewItem *sel) -{ - new_network = true; - - /* SSID BSSID frequency signal flags */ - setCaption(sel->text(0)); - ssidEdit->setText(sel->text(0)); - - QString flags = sel->text(4); - int auth, encr = 0; - if (flags.find("[WPA2-EAP") >= 0) - auth = AUTH_WPA2_EAP; - else if (flags.find("[WPA-EAP") >= 0) - auth = AUTH_WPA_EAP; - else if (flags.find("[WPA2-PSK") >= 0) - auth = AUTH_WPA2_PSK; - else if (flags.find("[WPA-PSK") >= 0) - auth = AUTH_WPA_PSK; - else - auth = AUTH_NONE; - - if (flags.find("-CCMP") >= 0) - encr = 1; - else if (flags.find("-TKIP") >= 0) - encr = 0; - else if (flags.find("WEP") >= 0) - encr = 1; - else - encr = 0; - - authSelect->setCurrentItem(auth); - authChanged(auth); - encrSelect->setCurrentItem(encr); - - getEapCapa(); -} - - -void NetworkConfig::authChanged(int sel) -{ - pskEdit->setEnabled(sel == AUTH_WPA_PSK || sel == AUTH_WPA2_PSK); - bool eap = sel == AUTH_IEEE8021X || sel == AUTH_WPA_EAP || - sel == AUTH_WPA2_EAP; - eapSelect->setEnabled(eap); - identityEdit->setEnabled(eap); - passwordEdit->setEnabled(eap); - cacertEdit->setEnabled(eap); - - while (encrSelect->count()) - encrSelect->removeItem(0); - - if (sel == AUTH_NONE || sel == AUTH_IEEE8021X) { - encrSelect->insertItem("None"); - encrSelect->insertItem("WEP"); - encrSelect->setCurrentItem(sel == AUTH_NONE ? 0 : 1); - } else { - encrSelect->insertItem("TKIP"); - encrSelect->insertItem("CCMP"); - encrSelect->setCurrentItem((sel == AUTH_WPA2_PSK || - sel == AUTH_WPA2_EAP) ? 1 : 0); - } - - wepEnabled(sel == AUTH_IEEE8021X); -} - - -void NetworkConfig::addNetwork() -{ - char reply[10], cmd[256]; - size_t reply_len; - int id; - int psklen = pskEdit->text().length(); - int auth = authSelect->currentItem(); - - if (auth == AUTH_WPA_PSK || auth == AUTH_WPA2_PSK) { - if (psklen < 8 || psklen > 64) { - QMessageBox::warning(this, "wpa_gui", - "WPA-PSK requires a passphrase " - "of 8 to 63 characters\n" - "or 64 hex digit PSK"); - return; - } - } - - if (wpagui == NULL) - return; - - memset(reply, 0, sizeof(reply)); - reply_len = sizeof(reply) - 1; - - if (new_network) { - wpagui->ctrlRequest("ADD_NETWORK", reply, &reply_len); - if (reply[0] == 'F') { - QMessageBox::warning(this, "wpa_gui", "Failed to add " - "network to wpa_supplicant\n" - "configuration."); - return; - } - id = atoi(reply); - } else - id = edit_network_id; - - setNetworkParam(id, "ssid", ssidEdit->text().ascii(), true); - - const char *key_mgmt = NULL, *proto = NULL, *pairwise = NULL; - switch (auth) { - case AUTH_NONE: - key_mgmt = "NONE"; - break; - case AUTH_IEEE8021X: - key_mgmt = "IEEE8021X"; - break; - case AUTH_WPA_PSK: - key_mgmt = "WPA-PSK"; - proto = "WPA"; - break; - case AUTH_WPA_EAP: - key_mgmt = "WPA-EAP"; - proto = "WPA"; - break; - case AUTH_WPA2_PSK: - key_mgmt = "WPA-PSK"; - proto = "WPA2"; - break; - case AUTH_WPA2_EAP: - key_mgmt = "WPA-EAP"; - proto = "WPA2"; - break; - } - - if (auth == AUTH_WPA_PSK || auth == AUTH_WPA_EAP || - auth == AUTH_WPA2_PSK || auth == AUTH_WPA2_EAP) { - int encr = encrSelect->currentItem(); - if (encr == 0) - pairwise = "TKIP"; - else - pairwise = "CCMP"; - } - - if (proto) - setNetworkParam(id, "proto", proto, false); - if (key_mgmt) - setNetworkParam(id, "key_mgmt", key_mgmt, false); - if (pairwise) { - setNetworkParam(id, "pairwise", pairwise, false); - setNetworkParam(id, "group", "TKIP CCMP WEP104 WEP40", false); - } - if (pskEdit->isEnabled() && - strcmp(passwordEdit->text().ascii(), WPA_GUI_KEY_DATA) != 0) - setNetworkParam(id, "psk", pskEdit->text().ascii(), - psklen != 64); - if (eapSelect->isEnabled()) - setNetworkParam(id, "eap", eapSelect->currentText().ascii(), - false); - if (identityEdit->isEnabled()) - setNetworkParam(id, "identity", identityEdit->text().ascii(), - true); - if (passwordEdit->isEnabled() && - strcmp(passwordEdit->text().ascii(), WPA_GUI_KEY_DATA) != 0) - setNetworkParam(id, "password", passwordEdit->text().ascii(), - true); - if (cacertEdit->isEnabled()) - setNetworkParam(id, "ca_cert", cacertEdit->text().ascii(), - true); - writeWepKey(id, wep0Edit, 0); - writeWepKey(id, wep1Edit, 1); - writeWepKey(id, wep2Edit, 2); - writeWepKey(id, wep3Edit, 3); - - if (wep0Radio->isEnabled() && wep0Radio->isChecked()) - setNetworkParam(id, "wep_tx_keyidx", "0", false); - else if (wep1Radio->isEnabled() && wep1Radio->isChecked()) - setNetworkParam(id, "wep_tx_keyidx", "1", false); - else if (wep2Radio->isEnabled() && wep2Radio->isChecked()) - setNetworkParam(id, "wep_tx_keyidx", "2", false); - else if (wep3Radio->isEnabled() && wep3Radio->isChecked()) - setNetworkParam(id, "wep_tx_keyidx", "3", false); - - snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %d", id); - reply_len = sizeof(reply); - wpagui->ctrlRequest(cmd, reply, &reply_len); - if (strncmp(reply, "OK", 2) != 0) { - QMessageBox::warning(this, "wpa_gui", "Failed to enable " - "network in wpa_supplicant\n" - "configuration."); - /* Network was added, so continue anyway */ - } - wpagui->triggerUpdate(); - wpagui->ctrlRequest("SAVE_CONFIG", reply, &reply_len); - - close(); -} - - -void NetworkConfig::setWpaGui(WpaGui *_wpagui) -{ - wpagui = _wpagui; -} - - -int NetworkConfig::setNetworkParam(int id, const char *field, - const char *value, bool quote) -{ - char reply[10], cmd[256]; - size_t reply_len; - snprintf(cmd, sizeof(cmd), "SET_NETWORK %d %s %s%s%s", - id, field, quote ? "\"" : "", value, quote ? "\"" : ""); - reply_len = sizeof(reply); - wpagui->ctrlRequest(cmd, reply, &reply_len); - return strncmp(reply, "OK", 2) == 0 ? 0 : -1; -} - - -void NetworkConfig::encrChanged(const QString &sel) -{ - wepEnabled(sel.find("WEP") == 0); -} - - -void NetworkConfig::wepEnabled(bool enabled) -{ - wep0Edit->setEnabled(enabled); - wep1Edit->setEnabled(enabled); - wep2Edit->setEnabled(enabled); - wep3Edit->setEnabled(enabled); - wep0Radio->setEnabled(enabled); - wep1Radio->setEnabled(enabled); - wep2Radio->setEnabled(enabled); - wep3Radio->setEnabled(enabled); -} - - -void NetworkConfig::writeWepKey(int network_id, QLineEdit *edit, int id) -{ - char buf[10]; - bool hex; - const char *txt, *pos; - size_t len; - - if (!edit->isEnabled() || edit->text().isEmpty()) - return; - - /* - * Assume hex key if only hex characters are present and length matches - * with 40, 104, or 128-bit key - */ - txt = edit->text().ascii(); - if (strcmp(txt, WPA_GUI_KEY_DATA) == 0) - return; - len = strlen(txt); - if (len == 0) - return; - pos = txt; - hex = true; - while (*pos) { - if (!((*pos >= '0' && *pos <= '9') || - (*pos >= 'a' && *pos <= 'f') || - (*pos >= 'A' && *pos <= 'F'))) { - hex = false; - break; - } - pos++; - } - if (hex && len != 10 && len != 26 && len != 32) - hex = false; - snprintf(buf, sizeof(buf), "wep_key%d", id); - setNetworkParam(network_id, buf, txt, !hex); -} - - -static int key_value_isset(const char *reply, size_t reply_len) -{ - return reply_len > 0 && (reply_len < 4 || memcmp(reply, "FAIL", 4) != 0); -} - - -void NetworkConfig::paramsFromConfig(int network_id) -{ - int i, res; - - edit_network_id = network_id; - getEapCapa(); - - char reply[1024], cmd[256], *pos; - size_t reply_len; - - snprintf(cmd, sizeof(cmd), "GET_NETWORK %d ssid", network_id); - reply_len = sizeof(reply) - 1; - if (wpagui->ctrlRequest(cmd, reply, &reply_len) >= 0 && - reply_len >= 2 && reply[0] == '"') { - reply[reply_len] = '\0'; - pos = strchr(reply + 1, '"'); - if (pos) - *pos = '\0'; - ssidEdit->setText(reply + 1); - } - - snprintf(cmd, sizeof(cmd), "GET_NETWORK %d proto", network_id); - reply_len = sizeof(reply) - 1; - int wpa = 0; - if (wpagui->ctrlRequest(cmd, reply, &reply_len) >= 0) { - reply[reply_len] = '\0'; - if (strstr(reply, "RSN") || strstr(reply, "WPA2")) - wpa = 2; - else if (strstr(reply, "WPA")) - wpa = 1; - } - - int auth = AUTH_NONE, encr = 0; - snprintf(cmd, sizeof(cmd), "GET_NETWORK %d key_mgmt", network_id); - reply_len = sizeof(reply) - 1; - if (wpagui->ctrlRequest(cmd, reply, &reply_len) >= 0) { - reply[reply_len] = '\0'; - if (strstr(reply, "WPA-EAP")) - auth = wpa & 2 ? AUTH_WPA2_EAP : AUTH_WPA_EAP; - else if (strstr(reply, "WPA-PSK")) - auth = wpa & 2 ? AUTH_WPA2_PSK : AUTH_WPA_PSK; - else if (strstr(reply, "IEEE8021X")) { - auth = AUTH_IEEE8021X; - encr = 1; - } - } - - snprintf(cmd, sizeof(cmd), "GET_NETWORK %d pairwise", network_id); - reply_len = sizeof(reply) - 1; - if (wpagui->ctrlRequest(cmd, reply, &reply_len) >= 0) { - reply[reply_len] = '\0'; - if (strstr(reply, "CCMP")) - encr = 1; - else if (strstr(reply, "TKIP")) - encr = 0; - else if (strstr(reply, "WEP")) - encr = 1; - else - encr = 0; - } - - snprintf(cmd, sizeof(cmd), "GET_NETWORK %d psk", network_id); - reply_len = sizeof(reply) - 1; - res = wpagui->ctrlRequest(cmd, reply, &reply_len); - if (res >= 0 && reply_len >= 2 && reply[0] == '"') { - reply[reply_len] = '\0'; - pos = strchr(reply + 1, '"'); - if (pos) - *pos = '\0'; - pskEdit->setText(reply + 1); - } else if (res >= 0 && key_value_isset(reply, reply_len)) { - pskEdit->setText(WPA_GUI_KEY_DATA); - } - - snprintf(cmd, sizeof(cmd), "GET_NETWORK %d identity", network_id); - reply_len = sizeof(reply) - 1; - if (wpagui->ctrlRequest(cmd, reply, &reply_len) >= 0 && - reply_len >= 2 && reply[0] == '"') { - reply[reply_len] = '\0'; - pos = strchr(reply + 1, '"'); - if (pos) - *pos = '\0'; - identityEdit->setText(reply + 1); - } - - snprintf(cmd, sizeof(cmd), "GET_NETWORK %d password", network_id); - reply_len = sizeof(reply) - 1; - res = wpagui->ctrlRequest(cmd, reply, &reply_len); - if (res >= 0 && reply_len >= 2 && reply[0] == '"') { - reply[reply_len] = '\0'; - pos = strchr(reply + 1, '"'); - if (pos) - *pos = '\0'; - passwordEdit->setText(reply + 1); - } else if (res >= 0 && key_value_isset(reply, reply_len)) { - passwordEdit->setText(WPA_GUI_KEY_DATA); - } - - snprintf(cmd, sizeof(cmd), "GET_NETWORK %d ca_cert", network_id); - reply_len = sizeof(reply) - 1; - if (wpagui->ctrlRequest(cmd, reply, &reply_len) >= 0 && - reply_len >= 2 && reply[0] == '"') { - reply[reply_len] = '\0'; - pos = strchr(reply + 1, '"'); - if (pos) - *pos = '\0'; - cacertEdit->setText(reply + 1); - } - - snprintf(cmd, sizeof(cmd), "GET_NETWORK %d eap", network_id); - reply_len = sizeof(reply) - 1; - if (wpagui->ctrlRequest(cmd, reply, &reply_len) >= 0 && - reply_len >= 1) { - reply[reply_len] = '\0'; - for (i = 0; i < eapSelect->count(); i++) { - if (eapSelect->text(i).compare(reply) == 0) { - eapSelect->setCurrentItem(i); - break; - } - } - } - - for (i = 0; i < 4; i++) { - QLineEdit *wepEdit; - switch (i) { - default: - case 0: - wepEdit = wep0Edit; - break; - case 1: - wepEdit = wep1Edit; - break; - case 2: - wepEdit = wep2Edit; - break; - case 3: - wepEdit = wep3Edit; - break; - } - snprintf(cmd, sizeof(cmd), "GET_NETWORK %d wep_key%d", - network_id, i); - reply_len = sizeof(reply) - 1; - res = wpagui->ctrlRequest(cmd, reply, &reply_len); - if (res >= 0 && reply_len >= 2 && reply[0] == '"') { - reply[reply_len] = '\0'; - pos = strchr(reply + 1, '"'); - if (pos) - *pos = '\0'; - if (auth == AUTH_NONE || auth == AUTH_IEEE8021X) - encr = 1; - - wepEdit->setText(reply + 1); - } else if (res >= 0 && key_value_isset(reply, reply_len)) { - if (auth == AUTH_NONE || auth == AUTH_IEEE8021X) - encr = 1; - wepEdit->setText(WPA_GUI_KEY_DATA); - } - } - - snprintf(cmd, sizeof(cmd), "GET_NETWORK %d wep_tx_keyidx", network_id); - reply_len = sizeof(reply) - 1; - if (wpagui->ctrlRequest(cmd, reply, &reply_len) >= 0 && reply_len >= 1) - { - reply[reply_len] = '\0'; - switch (atoi(reply)) { - case 0: - wep0Radio->setChecked(true); - break; - case 1: - wep1Radio->setChecked(true); - break; - case 2: - wep2Radio->setChecked(true); - break; - case 3: - wep3Radio->setChecked(true); - break; - } - } - - authSelect->setCurrentItem(auth); - authChanged(auth); - encrSelect->setCurrentItem(encr); - if (auth == AUTH_NONE || auth == AUTH_IEEE8021X) - wepEnabled(encr == 1); - - removeButton->setEnabled(true); - addButton->setText("Save"); -} - - -void NetworkConfig::removeNetwork() -{ - char reply[10], cmd[256]; - size_t reply_len; - - if (QMessageBox::information(this, "wpa_gui", - "This will permanently remove the " - "network\n" - "from the configuration. Do you really " - "want\n" - "to remove this network?", "Yes", "No") - != 0) - return; - - snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %d", edit_network_id); - reply_len = sizeof(reply); - wpagui->ctrlRequest(cmd, reply, &reply_len); - if (strncmp(reply, "OK", 2) != 0) { - QMessageBox::warning(this, "wpa_gui", - "Failed to remove network from " - "wpa_supplicant\n" - "configuration."); - } else { - wpagui->triggerUpdate(); - wpagui->ctrlRequest("SAVE_CONFIG", reply, &reply_len); - } - - close(); -} - - -void NetworkConfig::newNetwork() -{ - new_network = true; - getEapCapa(); -} - - -void NetworkConfig::getEapCapa() -{ - char reply[256]; - size_t reply_len; - - if (wpagui == NULL) - return; - - reply_len = sizeof(reply) - 1; - if (wpagui->ctrlRequest("GET_CAPABILITY eap", reply, &reply_len) < 0) - return; - reply[reply_len] = '\0'; - - QString res(reply); - QStringList types = QStringList::split(QChar(' '), res); - eapSelect->insertStringList(types); -} diff --git a/contrib/wpa_supplicant/wpa_gui-qt4/networkconfig.h b/contrib/wpa_supplicant/wpa_gui-qt4/networkconfig.h deleted file mode 100644 index 5a12d70f1f21..000000000000 --- a/contrib/wpa_supplicant/wpa_gui-qt4/networkconfig.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * wpa_gui - NetworkConfig class - * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 NETWORKCONFIG_H -#define NETWORKCONFIG_H - -#include <QObject> -#include "ui_networkconfig.h" - -class WpaGui; - -class NetworkConfig : public QDialog, public Ui::NetworkConfig -{ - Q_OBJECT - -public: - NetworkConfig(QWidget *parent = 0, const char *name = 0, - bool modal = false, Qt::WFlags fl = 0); - ~NetworkConfig(); - - virtual void paramsFromScanResults(Q3ListViewItem *sel); - virtual void setWpaGui(WpaGui *_wpagui); - virtual int setNetworkParam(int id, const char *field, - const char *value, bool quote); - virtual void paramsFromConfig(int network_id); - virtual void newNetwork(); - -public slots: - virtual void authChanged(int sel); - virtual void addNetwork(); - virtual void encrChanged(const QString &sel); - virtual void writeWepKey(int network_id, QLineEdit *edit, int id); - virtual void removeNetwork(); - -protected slots: - virtual void languageChange(); - -private: - WpaGui *wpagui; - int edit_network_id; - bool new_network; - - virtual void wepEnabled(bool enabled); - virtual void getEapCapa(); -}; - -#endif /* NETWORKCONFIG_H */ diff --git a/contrib/wpa_supplicant/wpa_gui-qt4/networkconfig.ui b/contrib/wpa_supplicant/wpa_gui-qt4/networkconfig.ui deleted file mode 100644 index 6b15da4af69b..000000000000 --- a/contrib/wpa_supplicant/wpa_gui-qt4/networkconfig.ui +++ /dev/null @@ -1,356 +0,0 @@ -<ui version="4.0" stdsetdef="1" > - <author></author> - <comment></comment> - <exportmacro></exportmacro> - <class>NetworkConfig</class> - <widget class="QDialog" name="NetworkConfig" > - <property name="geometry" > - <rect> - <x>0</x> - <y>0</y> - <width>380</width> - <height>413</height> - </rect> - </property> - <property name="windowTitle" > - <string>NetworkConfig</string> - </property> - <layout class="QGridLayout" > - <item row="1" column="3" > - <widget class="QPushButton" name="cancelButton" > - <property name="text" > - <string>Cancel</string> - </property> - </widget> - </item> - <item rowspan="1" row="0" column="0" colspan="4" > - <widget class="QFrame" name="frame9" > - <property name="frameShape" > - <enum>StyledPanel</enum> - </property> - <property name="frameShadow" > - <enum>Raised</enum> - </property> - <layout class="QGridLayout" > - <item row="0" column="0" > - <widget class="QLabel" name="textLabel1" > - <property name="text" > - <string>SSID</string> - </property> - </widget> - </item> - <item row="0" column="1" > - <widget class="QLineEdit" name="ssidEdit" > - <property name="text" > - <string/> - </property> - <property name="toolTip" stdset="0" > - <string>Network name (Service Set IDentifier)</string> - </property> - </widget> - </item> - <item row="1" column="0" > - <widget class="QLabel" name="textLabel2" > - <property name="text" > - <string>Authentication</string> - </property> - </widget> - </item> - <item row="1" column="1" > - <widget class="QComboBox" name="authSelect" > - <item> - <property name="text" > - <string>Plaintext or static WEP</string> - </property> - </item> - <item> - <property name="text" > - <string>IEEE 802.1X</string> - </property> - </item> - <item> - <property name="text" > - <string>WPA-Personal (PSK)</string> - </property> - </item> - <item> - <property name="text" > - <string>WPA-Enterprise (EAP)</string> - </property> - </item> - <item> - <property name="text" > - <string>WPA2-Personal (PSK)</string> - </property> - </item> - <item> - <property name="text" > - <string>WPA2-Enterprise (EAP)</string> - </property> - </item> - </widget> - </item> - <item row="2" column="0" > - <widget class="QLabel" name="textLabel3" > - <property name="text" > - <string>Encryption</string> - </property> - </widget> - </item> - <item row="2" column="1" > - <widget class="QComboBox" name="encrSelect" > - <item> - <property name="text" > - <string>None</string> - </property> - </item> - <item> - <property name="text" > - <string>WEP</string> - </property> - </item> - <item> - <property name="text" > - <string>TKIP</string> - </property> - </item> - <item> - <property name="text" > - <string>CCMP</string> - </property> - </item> - </widget> - </item> - <item row="3" column="0" > - <widget class="QLabel" name="textLabel4" > - <property name="text" > - <string>PSK</string> - </property> - </widget> - </item> - <item row="3" column="1" > - <widget class="QLineEdit" name="pskEdit" > - <property name="enabled" > - <bool>false</bool> - </property> - <property name="echoMode" > - <enum>QLineEdit::Password</enum> - </property> - <property name="toolTip" stdset="0" > - <string>WPA/WPA2 pre-shared key or passphrase</string> - </property> - <property name="whatsThis" stdset="0" > - <string/> - </property> - </widget> - </item> - <item row="4" column="0" > - <widget class="QLabel" name="textLabel5" > - <property name="text" > - <string>EAP method</string> - </property> - </widget> - </item> - <item row="4" column="1" > - <widget class="QComboBox" name="eapSelect" > - <property name="enabled" > - <bool>false</bool> - </property> - </widget> - </item> - <item row="5" column="0" > - <widget class="QLabel" name="textLabel6" > - <property name="text" > - <string>Identity</string> - </property> - </widget> - </item> - <item row="5" column="1" > - <widget class="QLineEdit" name="identityEdit" > - <property name="enabled" > - <bool>false</bool> - </property> - <property name="toolTip" stdset="0" > - <string>Username/Identity for EAP methods</string> - </property> - </widget> - </item> - <item row="6" column="0" > - <widget class="QLabel" name="textLabel7" > - <property name="text" > - <string>Password</string> - </property> - </widget> - </item> - <item row="6" column="1" > - <widget class="QLineEdit" name="passwordEdit" > - <property name="enabled" > - <bool>false</bool> - </property> - <property name="echoMode" > - <enum>QLineEdit::Password</enum> - </property> - <property name="toolTip" stdset="0" > - <string>Password for EAP methods</string> - </property> - </widget> - </item> - <item row="7" column="0" > - <widget class="QLabel" name="textLabel1_2" > - <property name="text" > - <string>CA certificate</string> - </property> - </widget> - </item> - <item row="7" column="1" > - <widget class="QLineEdit" name="cacertEdit" > - <property name="enabled" > - <bool>false</bool> - </property> - </widget> - </item> - <item rowspan="1" row="8" column="0" colspan="2" > - <widget class="QGroupBox" name="buttonGroup1" > - <property name="enabled" > - <bool>true</bool> - </property> - <property name="title" > - <string>WEP keys</string> - </property> - <layout class="QGridLayout" > - <item row="0" column="0" > - <widget class="QRadioButton" name="wep0Radio" > - <property name="enabled" > - <bool>false</bool> - </property> - <property name="text" > - <string>key 0</string> - </property> - </widget> - </item> - <item row="1" column="0" > - <widget class="QRadioButton" name="wep1Radio" > - <property name="enabled" > - <bool>false</bool> - </property> - <property name="text" > - <string>key 1</string> - </property> - </widget> - </item> - <item row="3" column="0" > - <widget class="QRadioButton" name="wep3Radio" > - <property name="enabled" > - <bool>false</bool> - </property> - <property name="text" > - <string>key 3</string> - </property> - </widget> - </item> - <item row="2" column="0" > - <widget class="QRadioButton" name="wep2Radio" > - <property name="enabled" > - <bool>false</bool> - </property> - <property name="text" > - <string>key 2</string> - </property> - </widget> - </item> - <item row="0" column="1" > - <widget class="QLineEdit" name="wep0Edit" > - <property name="enabled" > - <bool>false</bool> - </property> - </widget> - </item> - <item row="1" column="1" > - <widget class="QLineEdit" name="wep1Edit" > - <property name="enabled" > - <bool>false</bool> - </property> - </widget> - </item> - <item row="2" column="1" > - <widget class="QLineEdit" name="wep2Edit" > - <property name="enabled" > - <bool>false</bool> - </property> - </widget> - </item> - <item row="3" column="1" > - <widget class="QLineEdit" name="wep3Edit" > - <property name="enabled" > - <bool>false</bool> - </property> - </widget> - </item> - </layout> - </widget> - </item> - </layout> - </widget> - </item> - <item row="1" column="0" > - <spacer name="spacer5" > - <property name="sizeHint" > - <size> - <width>130</width> - <height>20</height> - </size> - </property> - <property name="sizeType" > - <enum>Expanding</enum> - </property> - <property name="orientation" > - <enum>Horizontal</enum> - </property> - </spacer> - </item> - <item row="1" column="1" > - <widget class="QPushButton" name="addButton" > - <property name="text" > - <string>Add</string> - </property> - </widget> - </item> - <item row="1" column="2" > - <widget class="QPushButton" name="removeButton" > - <property name="enabled" > - <bool>false</bool> - </property> - <property name="text" > - <string>Remove</string> - </property> - </widget> - </item> - </layout> - </widget> - <layoutdefault spacing="6" margin="11" /> - <pixmapfunction>qPixmapFromMimeSource</pixmapfunction> - <tabstops> - <tabstop>ssidEdit</tabstop> - <tabstop>authSelect</tabstop> - <tabstop>encrSelect</tabstop> - <tabstop>pskEdit</tabstop> - <tabstop>eapSelect</tabstop> - <tabstop>identityEdit</tabstop> - <tabstop>passwordEdit</tabstop> - <tabstop>cacertEdit</tabstop> - <tabstop>wep0Radio</tabstop> - <tabstop>wep1Radio</tabstop> - <tabstop>wep2Radio</tabstop> - <tabstop>wep3Radio</tabstop> - <tabstop>wep0Edit</tabstop> - <tabstop>wep1Edit</tabstop> - <tabstop>wep2Edit</tabstop> - <tabstop>wep3Edit</tabstop> - <tabstop>addButton</tabstop> - <tabstop>removeButton</tabstop> - <tabstop>cancelButton</tabstop> - </tabstops> - <includes> - <include location="global" >q3listview.h</include> - </includes> -</ui> diff --git a/contrib/wpa_supplicant/wpa_gui-qt4/scanresults.cpp b/contrib/wpa_supplicant/wpa_gui-qt4/scanresults.cpp deleted file mode 100644 index 75d1c5146bfd..000000000000 --- a/contrib/wpa_supplicant/wpa_gui-qt4/scanresults.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* - * wpa_gui - ScanResults class - * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 <QTimer> - -#include <cstdio> - -#include "scanresults.h" -#include "wpagui.h" -#include "networkconfig.h" - - -ScanResults::ScanResults(QWidget *parent, const char *, bool, Qt::WFlags) - : QDialog(parent) -{ - setupUi(this); - - connect(closeButton, SIGNAL(clicked()), this, SLOT(close())); - connect(scanButton, SIGNAL(clicked()), this, SLOT(scanRequest())); - connect(scanResultsView, SIGNAL(doubleClicked(Q3ListViewItem *)), this, - SLOT(bssSelected(Q3ListViewItem *))); - - wpagui = NULL; -} - - -ScanResults::~ScanResults() -{ - delete timer; -} - - -void ScanResults::languageChange() -{ - retranslateUi(this); -} - - -void ScanResults::setWpaGui(WpaGui *_wpagui) -{ - wpagui = _wpagui; - updateResults(); - - timer = new QTimer(this); - connect(timer, SIGNAL(timeout()), SLOT(getResults())); - timer->start(10000, FALSE); -} - - -void ScanResults::updateResults() -{ - char reply[8192]; - size_t reply_len; - - if (wpagui == NULL) - return; - - reply_len = sizeof(reply) - 1; - if (wpagui->ctrlRequest("SCAN_RESULTS", reply, &reply_len) < 0) - return; - reply[reply_len] = '\0'; - - scanResultsView->clear(); - - QString res(reply); - QStringList lines = QStringList::split(QChar('\n'), res); - bool first = true; - for (QStringList::Iterator it = lines.begin(); it != lines.end(); it++) - { - if (first) { - first = false; - continue; - } - - QStringList cols = QStringList::split(QChar('\t'), *it, true); - QString ssid, bssid, freq, signal, flags; - bssid = cols.count() > 0 ? cols[0] : ""; - freq = cols.count() > 1 ? cols[1] : ""; - signal = cols.count() > 2 ? cols[2] : ""; - flags = cols.count() > 3 ? cols[3] : ""; - ssid = cols.count() > 4 ? cols[4] : ""; - new Q3ListViewItem(scanResultsView, ssid, bssid, freq, signal, - flags); - } -} - - -void ScanResults::scanRequest() -{ - char reply[10]; - size_t reply_len = sizeof(reply); - - if (wpagui == NULL) - return; - - wpagui->ctrlRequest("SCAN", reply, &reply_len); -} - - -void ScanResults::getResults() -{ - updateResults(); -} - - -void ScanResults::bssSelected( Q3ListViewItem * sel ) -{ - NetworkConfig *nc = new NetworkConfig(); - if (nc == NULL) - return; - nc->setWpaGui(wpagui); - nc->paramsFromScanResults(sel); - nc->show(); - nc->exec(); -} diff --git a/contrib/wpa_supplicant/wpa_gui-qt4/scanresults.h b/contrib/wpa_supplicant/wpa_gui-qt4/scanresults.h deleted file mode 100644 index 22b54c9b49e6..000000000000 --- a/contrib/wpa_supplicant/wpa_gui-qt4/scanresults.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * wpa_gui - ScanResults class - * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 SCANRESULTS_H -#define SCANRESULTS_H - -#include <QObject> -#include "ui_scanresults.h" - -class WpaGui; - -class ScanResults : public QDialog, public Ui::ScanResults -{ - Q_OBJECT - -public: - ScanResults(QWidget *parent = 0, const char *name = 0, - bool modal = false, Qt::WFlags fl = 0); - ~ScanResults(); - -public slots: - virtual void setWpaGui(WpaGui *_wpagui); - virtual void updateResults(); - virtual void scanRequest(); - virtual void getResults(); - virtual void bssSelected(Q3ListViewItem *sel); - -protected slots: - virtual void languageChange(); - -private: - WpaGui *wpagui; - QTimer *timer; -}; - -#endif /* SCANRESULTS_H */ diff --git a/contrib/wpa_supplicant/wpa_gui-qt4/scanresults.ui b/contrib/wpa_supplicant/wpa_gui-qt4/scanresults.ui deleted file mode 100644 index 4a49b05ca8ae..000000000000 --- a/contrib/wpa_supplicant/wpa_gui-qt4/scanresults.ui +++ /dev/null @@ -1,125 +0,0 @@ -<ui version="4.0" stdsetdef="1" > - <author></author> - <comment></comment> - <exportmacro></exportmacro> - <class>ScanResults</class> - <widget class="QDialog" name="ScanResults" > - <property name="geometry" > - <rect> - <x>0</x> - <y>0</y> - <width>452</width> - <height>225</height> - </rect> - </property> - <property name="windowTitle" > - <string>Scan results</string> - </property> - <layout class="QVBoxLayout" > - <item> - <widget class="Q3ListView" name="scanResultsView" > - <property name="frameShape" > - <enum>QFrame::StyledPanel</enum> - </property> - <property name="frameShadow" > - <enum>QFrame::Sunken</enum> - </property> - <column> - <property name="text" > - <string>SSID</string> - </property> - <property name="clickable" > - <bool>true</bool> - </property> - <property name="resizable" > - <bool>true</bool> - </property> - </column> - <column> - <property name="text" > - <string>BSSID</string> - </property> - <property name="clickable" > - <bool>true</bool> - </property> - <property name="resizable" > - <bool>true</bool> - </property> - </column> - <column> - <property name="text" > - <string>frequency</string> - </property> - <property name="clickable" > - <bool>true</bool> - </property> - <property name="resizable" > - <bool>true</bool> - </property> - </column> - <column> - <property name="text" > - <string>signal</string> - </property> - <property name="clickable" > - <bool>true</bool> - </property> - <property name="resizable" > - <bool>true</bool> - </property> - </column> - <column> - <property name="text" > - <string>flags</string> - </property> - <property name="clickable" > - <bool>true</bool> - </property> - <property name="resizable" > - <bool>true</bool> - </property> - </column> - </widget> - </item> - <item> - <layout class="QHBoxLayout" > - <property name="margin" > - <number>0</number> - </property> - <item> - <spacer name="spacer6" > - <property name="sizeHint" > - <size> - <width>50</width> - <height>20</height> - </size> - </property> - <property name="sizeType" > - <enum>Expanding</enum> - </property> - <property name="orientation" > - <enum>Horizontal</enum> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="scanButton" > - <property name="text" > - <string>Scan</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="closeButton" > - <property name="text" > - <string>Close</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - <layoutdefault spacing="6" margin="11" /> - <pixmapfunction>qPixmapFromMimeSource</pixmapfunction> -</ui> diff --git a/contrib/wpa_supplicant/wpa_gui-qt4/setup-mingw-cross-compiling b/contrib/wpa_supplicant/wpa_gui-qt4/setup-mingw-cross-compiling deleted file mode 100755 index e173b0013781..000000000000 --- a/contrib/wpa_supplicant/wpa_gui-qt4/setup-mingw-cross-compiling +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -# qmake seems to be forcing include and lib paths from the original build -# and I have no idea how to change these. For now, just override the -# directories in the Makefile.Release file after qmake run. - -qmake -spec /q/jm/qt4-win/4.0.0/mkspecs/win32-g++ wpa_gui.pro -o Makefile -cat Makefile.Release | - sed s%qt4/lib%qt4-win/4.0.0/lib%g | - sed s%qt4/include%qt4-win/4.0.0/include%g > tmp.Makefile.Release && -mv -f tmp.Makefile.Release Makefile.Release diff --git a/contrib/wpa_supplicant/wpa_gui-qt4/userdatarequest.cpp b/contrib/wpa_supplicant/wpa_gui-qt4/userdatarequest.cpp deleted file mode 100644 index e198955b4d93..000000000000 --- a/contrib/wpa_supplicant/wpa_gui-qt4/userdatarequest.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* - * wpa_gui - UserDataRequest class - * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 "userdatarequest.h" -#include "wpagui.h" -#include "wpa_ctrl.h" - - -UserDataRequest::UserDataRequest(QWidget *parent, const char *, bool, - Qt::WFlags) - : QDialog(parent) -{ - setupUi(this); - - connect(buttonOk, SIGNAL(clicked()), this, SLOT(sendReply())); - connect(buttonCancel, SIGNAL(clicked()), this, SLOT(reject())); - connect(queryEdit, SIGNAL(returnPressed()), this, SLOT(sendReply())); -} - - -UserDataRequest::~UserDataRequest() -{ -} - - -void UserDataRequest::languageChange() -{ - retranslateUi(this); -} - - -int UserDataRequest::setParams(WpaGui *_wpagui, const char *reqMsg) -{ - char *tmp, *pos, *pos2; - wpagui = _wpagui; - tmp = strdup(reqMsg); - if (tmp == NULL) - return -1; - pos = strchr(tmp, '-'); - if (pos == NULL) { - free(tmp); - return -1; - } - *pos++ = '\0'; - field = tmp; - pos2 = strchr(pos, ':'); - if (pos2 == NULL) { - free(tmp); - return -1; - } - *pos2++ = '\0'; - - networkid = atoi(pos); - queryInfo->setText(pos2); - if (strcmp(tmp, "PASSWORD") == 0) { - queryField->setText("Password: "); - queryEdit->setEchoMode(QLineEdit::Password); - } else if (strcmp(tmp, "NEW_PASSWORD") == 0) { - queryField->setText("New password: "); - queryEdit->setEchoMode(QLineEdit::Password); - } else if (strcmp(tmp, "IDENTITY") == 0) - queryField->setText("Identity: "); - else if (strcmp(tmp, "PASSPHRASE") == 0) { - queryField->setText("Private key passphrase: "); - queryEdit->setEchoMode(QLineEdit::Password); - } else - queryField->setText(field + ":"); - free(tmp); - - return 0; -} - - -void UserDataRequest::sendReply() -{ - char reply[10]; - size_t reply_len = sizeof(reply); - - if (wpagui == NULL) { - reject(); - return; - } - - QString cmd = QString(WPA_CTRL_RSP) + field + '-' + - QString::number(networkid) + ':' + - queryEdit->text(); - wpagui->ctrlRequest(cmd.ascii(), reply, &reply_len); - accept(); -} diff --git a/contrib/wpa_supplicant/wpa_gui-qt4/userdatarequest.h b/contrib/wpa_supplicant/wpa_gui-qt4/userdatarequest.h deleted file mode 100644 index 2b6e8371bc65..000000000000 --- a/contrib/wpa_supplicant/wpa_gui-qt4/userdatarequest.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * wpa_gui - UserDataRequest class - * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 USERDATAREQUEST_H -#define USERDATAREQUEST_H - -#include <QObject> -#include "ui_userdatarequest.h" - -class WpaGui; - -class UserDataRequest : public QDialog, public Ui::UserDataRequest -{ - Q_OBJECT - -public: - UserDataRequest(QWidget *parent = 0, const char *name = 0, - bool modal = false, Qt::WFlags fl = 0); - ~UserDataRequest(); - - int setParams(WpaGui *_wpagui, const char *reqMsg); - -public slots: - virtual void sendReply(); - -protected slots: - virtual void languageChange(); - -private: - WpaGui *wpagui; - int networkid; - QString field; -}; - -#endif /* USERDATAREQUEST_H */ diff --git a/contrib/wpa_supplicant/wpa_gui-qt4/userdatarequest.ui b/contrib/wpa_supplicant/wpa_gui-qt4/userdatarequest.ui deleted file mode 100644 index ea0172194987..000000000000 --- a/contrib/wpa_supplicant/wpa_gui-qt4/userdatarequest.ui +++ /dev/null @@ -1,109 +0,0 @@ -<ui version="4.0" stdsetdef="1" > - <author></author> - <comment></comment> - <exportmacro></exportmacro> - <class>UserDataRequest</class> - <widget class="QDialog" name="UserDataRequest" > - <property name="geometry" > - <rect> - <x>0</x> - <y>0</y> - <width>216</width> - <height>103</height> - </rect> - </property> - <property name="windowTitle" > - <string>Authentication credentials required</string> - </property> - <property name="sizeGripEnabled" > - <bool>true</bool> - </property> - <layout class="QVBoxLayout" > - <item> - <widget class="QLabel" name="queryInfo" > - <property name="text" > - <string/> - </property> - </widget> - </item> - <item> - <layout class="QHBoxLayout" > - <property name="margin" > - <number>0</number> - </property> - <item> - <widget class="QLabel" name="queryField" > - <property name="text" > - <string/> - </property> - </widget> - </item> - <item> - <widget class="QLineEdit" name="queryEdit" > - <property name="enabled" > - <bool>true</bool> - </property> - <property name="echoMode" > - <enum>QLineEdit::Password</enum> - </property> - </widget> - </item> - </layout> - </item> - <item> - <layout class="QHBoxLayout" > - <property name="margin" > - <number>0</number> - </property> - <item> - <spacer name="spacer4" > - <property name="sizeHint" > - <size> - <width>20</width> - <height>20</height> - </size> - </property> - <property name="sizeType" > - <enum>Expanding</enum> - </property> - <property name="orientation" > - <enum>Horizontal</enum> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="buttonOk" > - <property name="text" > - <string>&OK</string> - </property> - <property name="shortcut" > - <string/> - </property> - <property name="autoDefault" > - <bool>true</bool> - </property> - <property name="default" > - <bool>true</bool> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="buttonCancel" > - <property name="text" > - <string>&Cancel</string> - </property> - <property name="shortcut" > - <string/> - </property> - <property name="autoDefault" > - <bool>true</bool> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - <layoutdefault spacing="6" margin="11" /> - <pixmapfunction>qPixmapFromMimeSource</pixmapfunction> -</ui> diff --git a/contrib/wpa_supplicant/wpa_gui-qt4/wpa_gui.pro b/contrib/wpa_supplicant/wpa_gui-qt4/wpa_gui.pro deleted file mode 100644 index 0d1c32b5714c..000000000000 --- a/contrib/wpa_supplicant/wpa_gui-qt4/wpa_gui.pro +++ /dev/null @@ -1,50 +0,0 @@ -TEMPLATE = app -LANGUAGE = C++ - -CONFIG += qt warn_on release - -DEFINES += CONFIG_CTRL_IFACE - -win32 { - LIBS += -lws2_32 -static - DEFINES += CONFIG_NATIVE_WINDOWS CONFIG_CTRL_IFACE_NAMED_PIPE -} else:win32-g++ { - # cross compilation to win32 - LIBS += -lws2_32 -static - DEFINES += CONFIG_NATIVE_WINDOWS CONFIG_CTRL_IFACE_NAMED_PIPE -} else { - DEFINES += CONFIG_CTRL_IFACE_UNIX -} - -INCLUDEPATH += . .. ../../hostapd - -HEADERS += wpamsg.h \ - wpagui.h \ - eventhistory.h \ - scanresults.h \ - userdatarequest.h \ - networkconfig.h - -SOURCES += main.cpp \ - wpagui.cpp \ - eventhistory.cpp \ - scanresults.cpp \ - userdatarequest.cpp \ - networkconfig.cpp \ - ../wpa_ctrl.c - -FORMS = wpagui.ui \ - eventhistory.ui \ - scanresults.ui \ - userdatarequest.ui \ - networkconfig.ui - - -unix { - UI_DIR = .ui - MOC_DIR = .moc - OBJECTS_DIR = .obj -} - -# TODO: remove need for Qt3 support code -QT += qt3support diff --git a/contrib/wpa_supplicant/wpa_gui-qt4/wpagui.cpp b/contrib/wpa_supplicant/wpa_gui-qt4/wpagui.cpp deleted file mode 100644 index 798786b68645..000000000000 --- a/contrib/wpa_supplicant/wpa_gui-qt4/wpagui.cpp +++ /dev/null @@ -1,780 +0,0 @@ -/* - * wpa_gui - WpaGui class - * Copyright (c) 2005-2008, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 __MINGW32__ -/* Need to get getopt() */ -#include <unistd.h> -#endif - -#include <cstdio> -#include <QMessageBox> - -#include "wpagui.h" -#include "dirent.h" -#include "wpa_ctrl.h" -#include "userdatarequest.h" -#include "networkconfig.h" - -WpaGui::WpaGui(QWidget *parent, const char *, Qt::WFlags) - : QMainWindow(parent) -{ - setupUi(this); - - (void) statusBar(); - - connect(helpIndexAction, SIGNAL(activated()), this, SLOT(helpIndex())); - connect(helpContentsAction, SIGNAL(activated()), this, - SLOT(helpContents())); - connect(helpAboutAction, SIGNAL(activated()), this, SLOT(helpAbout())); - connect(fileExitAction, SIGNAL(activated()), this, SLOT(close())); - connect(disconnectButton, SIGNAL(clicked()), this, SLOT(disconnect())); - connect(scanButton, SIGNAL(clicked()), this, SLOT(scan())); - connect(connectButton, SIGNAL(clicked()), this, SLOT(connectB())); - connect(fileEventHistoryAction, SIGNAL(activated()), this, - SLOT(eventHistory())); - connect(networkSelect, SIGNAL(activated(const QString&)), this, - SLOT(selectNetwork(const QString&))); - connect(fileEdit_networkAction, SIGNAL(activated()), this, - SLOT(editNetwork())); - connect(fileAdd_NetworkAction, SIGNAL(activated()), this, - SLOT(addNetwork())); - connect(adapterSelect, SIGNAL(activated(const QString&)), this, - SLOT(selectAdapter(const QString&))); - - eh = NULL; - scanres = NULL; - udr = NULL; - ctrl_iface = NULL; - ctrl_conn = NULL; - monitor_conn = NULL; - msgNotifier = NULL; - ctrl_iface_dir = strdup("/var/run/wpa_supplicant"); - - parse_argv(); - - textStatus->setText("connecting to wpa_supplicant"); - timer = new QTimer(this); - connect(timer, SIGNAL(timeout()), SLOT(ping())); - timer->start(1000, FALSE); - - if (openCtrlConnection(ctrl_iface) < 0) { - printf("Failed to open control connection to " - "wpa_supplicant.\n"); - } - - updateStatus(); - networkMayHaveChanged = true; - updateNetworks(); -} - - -WpaGui::~WpaGui() -{ - delete msgNotifier; - - if (monitor_conn) { - wpa_ctrl_detach(monitor_conn); - wpa_ctrl_close(monitor_conn); - monitor_conn = NULL; - } - if (ctrl_conn) { - wpa_ctrl_close(ctrl_conn); - ctrl_conn = NULL; - } - - if (eh) { - eh->close(); - delete eh; - eh = NULL; - } - - if (scanres) { - scanres->close(); - delete scanres; - scanres = NULL; - } - - if (udr) { - udr->close(); - delete udr; - udr = NULL; - } - - free(ctrl_iface); - ctrl_iface = NULL; - - free(ctrl_iface_dir); - ctrl_iface_dir = NULL; -} - - -void WpaGui::languageChange() -{ - retranslateUi(this); -} - - -void WpaGui::parse_argv() -{ - int c; - for (;;) { - c = getopt(qApp->argc(), qApp->argv(), "i:p:"); - if (c < 0) - break; - switch (c) { - case 'i': - free(ctrl_iface); - ctrl_iface = strdup(optarg); - break; - case 'p': - free(ctrl_iface_dir); - ctrl_iface_dir = strdup(optarg); - break; - } - } -} - - -int WpaGui::openCtrlConnection(const char *ifname) -{ - char *cfile; - int flen; - char buf[2048], *pos, *pos2; - size_t len; - - if (ifname) { - if (ifname != ctrl_iface) { - free(ctrl_iface); - ctrl_iface = strdup(ifname); - } - } else { -#ifdef CONFIG_CTRL_IFACE_UDP - free(ctrl_iface); - ctrl_iface = strdup("udp"); -#endif /* CONFIG_CTRL_IFACE_UDP */ -#ifdef CONFIG_CTRL_IFACE_UNIX - struct dirent *dent; - DIR *dir = opendir(ctrl_iface_dir); - free(ctrl_iface); - ctrl_iface = NULL; - if (dir) { - 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; - printf("Selected interface '%s'\n", - dent->d_name); - ctrl_iface = strdup(dent->d_name); - break; - } - closedir(dir); - } -#endif /* CONFIG_CTRL_IFACE_UNIX */ -#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE - struct wpa_ctrl *ctrl; - int ret; - - free(ctrl_iface); - ctrl_iface = NULL; - - ctrl = wpa_ctrl_open(NULL); - if (ctrl) { - len = sizeof(buf) - 1; - ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, - &len, NULL); - if (ret >= 0) { - buf[len] = '\0'; - pos = strchr(buf, '\n'); - if (pos) - *pos = '\0'; - ctrl_iface = strdup(buf); - } - wpa_ctrl_close(ctrl); - } -#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ - } - - if (ctrl_iface == NULL) - return -1; - -#ifdef CONFIG_CTRL_IFACE_UNIX - flen = strlen(ctrl_iface_dir) + strlen(ctrl_iface) + 2; - cfile = (char *) malloc(flen); - if (cfile == NULL) - return -1; - snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ctrl_iface); -#else /* CONFIG_CTRL_IFACE_UNIX */ - flen = strlen(ctrl_iface) + 1; - cfile = (char *) malloc(flen); - if (cfile == NULL) - return -1; - snprintf(cfile, flen, "%s", ctrl_iface); -#endif /* CONFIG_CTRL_IFACE_UNIX */ - - if (ctrl_conn) { - wpa_ctrl_close(ctrl_conn); - ctrl_conn = NULL; - } - - if (monitor_conn) { - delete msgNotifier; - msgNotifier = NULL; - wpa_ctrl_detach(monitor_conn); - wpa_ctrl_close(monitor_conn); - monitor_conn = NULL; - } - - printf("Trying to connect to '%s'\n", cfile); - ctrl_conn = wpa_ctrl_open(cfile); - if (ctrl_conn == NULL) { - free(cfile); - return -1; - } - monitor_conn = wpa_ctrl_open(cfile); - free(cfile); - if (monitor_conn == NULL) { - wpa_ctrl_close(ctrl_conn); - return -1; - } - if (wpa_ctrl_attach(monitor_conn)) { - printf("Failed to attach to wpa_supplicant\n"); - wpa_ctrl_close(monitor_conn); - monitor_conn = NULL; - wpa_ctrl_close(ctrl_conn); - ctrl_conn = NULL; - return -1; - } - -#if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP) - msgNotifier = new QSocketNotifier(wpa_ctrl_get_fd(monitor_conn), - QSocketNotifier::Read, this); - connect(msgNotifier, SIGNAL(activated(int)), SLOT(receiveMsgs())); -#endif - - adapterSelect->clear(); - adapterSelect->insertItem(ctrl_iface); - adapterSelect->setCurrentItem(0); - - len = sizeof(buf) - 1; - if (wpa_ctrl_request(ctrl_conn, "INTERFACES", 10, buf, &len, NULL) >= - 0) { - buf[len] = '\0'; - pos = buf; - while (*pos) { - pos2 = strchr(pos, '\n'); - if (pos2) - *pos2 = '\0'; - if (strcmp(pos, ctrl_iface) != 0) - adapterSelect->insertItem(pos); - if (pos2) - pos = pos2 + 1; - else - break; - } - } - - return 0; -} - - -static void wpa_gui_msg_cb(char *msg, size_t) -{ - /* This should not happen anymore since two control connections are - * used. */ - printf("missed message: %s\n", msg); -} - - -int WpaGui::ctrlRequest(const char *cmd, char *buf, size_t *buflen) -{ - int ret; - - if (ctrl_conn == NULL) - return -3; - ret = wpa_ctrl_request(ctrl_conn, cmd, strlen(cmd), buf, buflen, - wpa_gui_msg_cb); - if (ret == -2) - printf("'%s' command timed out.\n", cmd); - else if (ret < 0) - printf("'%s' command failed.\n", cmd); - - return ret; -} - - -void WpaGui::updateStatus() -{ - char buf[2048], *start, *end, *pos; - size_t len; - - pingsToStatusUpdate = 10; - - len = sizeof(buf) - 1; - if (ctrl_conn == NULL || ctrlRequest("STATUS", buf, &len) < 0) { - textStatus->setText("Could not get status from " - "wpa_supplicant"); - textAuthentication->clear(); - textEncryption->clear(); - textSsid->clear(); - textBssid->clear(); - textIpAddress->clear(); - return; - } - - buf[len] = '\0'; - - bool auth_updated = false, ssid_updated = false; - bool bssid_updated = false, ipaddr_updated = false; - bool status_updated = false; - char *pairwise_cipher = NULL, *group_cipher = NULL; - - start = buf; - while (*start) { - bool last = false; - end = strchr(start, '\n'); - if (end == NULL) { - last = true; - end = start; - while (end[0] && end[1]) - end++; - } - *end = '\0'; - - pos = strchr(start, '='); - if (pos) { - *pos++ = '\0'; - if (strcmp(start, "bssid") == 0) { - bssid_updated = true; - textBssid->setText(pos); - } else if (strcmp(start, "ssid") == 0) { - ssid_updated = true; - textSsid->setText(pos); - } else if (strcmp(start, "ip_address") == 0) { - ipaddr_updated = true; - textIpAddress->setText(pos); - } else if (strcmp(start, "wpa_state") == 0) { - status_updated = true; - textStatus->setText(pos); - } else if (strcmp(start, "key_mgmt") == 0) { - auth_updated = true; - textAuthentication->setText(pos); - /* TODO: could add EAP status to this */ - } else if (strcmp(start, "pairwise_cipher") == 0) { - pairwise_cipher = pos; - } else if (strcmp(start, "group_cipher") == 0) { - group_cipher = pos; - } - } - - if (last) - break; - start = end + 1; - } - - if (pairwise_cipher || group_cipher) { - QString encr; - if (pairwise_cipher && group_cipher && - strcmp(pairwise_cipher, group_cipher) != 0) { - encr.append(pairwise_cipher); - encr.append(" + "); - encr.append(group_cipher); - } else if (pairwise_cipher) { - encr.append(pairwise_cipher); - } else if (group_cipher) { - encr.append(group_cipher); - encr.append(" [group key only]"); - } else { - encr.append("?"); - } - textEncryption->setText(encr); - } else - textEncryption->clear(); - - if (!status_updated) - textStatus->clear(); - if (!auth_updated) - textAuthentication->clear(); - if (!ssid_updated) - textSsid->clear(); - if (!bssid_updated) - textBssid->clear(); - if (!ipaddr_updated) - textIpAddress->clear(); -} - - -void WpaGui::updateNetworks() -{ - char buf[2048], *start, *end, *id, *ssid, *bssid, *flags; - size_t len; - int first_active = -1; - bool selected = false; - - if (!networkMayHaveChanged) - return; - - networkSelect->clear(); - - if (ctrl_conn == NULL) - return; - - len = sizeof(buf) - 1; - if (ctrlRequest("LIST_NETWORKS", buf, &len) < 0) - return; - - buf[len] = '\0'; - start = strchr(buf, '\n'); - if (start == NULL) - return; - start++; - - while (*start) { - bool last = false; - end = strchr(start, '\n'); - if (end == NULL) { - last = true; - end = start; - while (end[0] && end[1]) - end++; - } - *end = '\0'; - - id = start; - ssid = strchr(id, '\t'); - if (ssid == NULL) - break; - *ssid++ = '\0'; - bssid = strchr(ssid, '\t'); - if (bssid == NULL) - break; - *bssid++ = '\0'; - flags = strchr(bssid, '\t'); - if (flags == NULL) - break; - *flags++ = '\0'; - - QString network(id); - network.append(": "); - network.append(ssid); - networkSelect->insertItem(network); - - if (strstr(flags, "[CURRENT]")) { - networkSelect->setCurrentItem(networkSelect->count() - - 1); - selected = true; - } else if (first_active < 0 && - strstr(flags, "[DISABLED]") == NULL) - first_active = networkSelect->count() - 1; - - if (last) - break; - start = end + 1; - } - - if (!selected && first_active >= 0) - networkSelect->setCurrentItem(first_active); - - networkMayHaveChanged = false; -} - - -void WpaGui::helpIndex() -{ - printf("helpIndex\n"); -} - - -void WpaGui::helpContents() -{ - printf("helpContents\n"); -} - - -void WpaGui::helpAbout() -{ - QMessageBox::about(this, "wpa_gui for wpa_supplicant", - "Copyright (c) 2003-2008,\n" - "Jouni Malinen <j@w1.fi>\n" - "and contributors.\n" - "\n" - "This program is free software. You can\n" - "distribute it and/or modify it under the terms " - "of\n" - "the GNU General Public License version 2.\n" - "\n" - "Alternatively, this software may be distributed\n" - "under the terms of the BSD license.\n" - "\n" - "This product includes software developed\n" - "by the OpenSSL Project for use in the\n" - "OpenSSL Toolkit (http://www.openssl.org/)\n"); -} - - -void WpaGui::disconnect() -{ - char reply[10]; - size_t reply_len = sizeof(reply); - ctrlRequest("DISCONNECT", reply, &reply_len); -} - - -void WpaGui::scan() -{ - if (scanres) { - scanres->close(); - delete scanres; - } - - scanres = new ScanResults(); - if (scanres == NULL) - return; - scanres->setWpaGui(this); - scanres->show(); - scanres->exec(); -} - - -void WpaGui::eventHistory() -{ - if (eh) { - eh->close(); - delete eh; - } - - eh = new EventHistory(); - if (eh == NULL) - return; - eh->addEvents(msgs); - eh->show(); - eh->exec(); -} - - -void WpaGui::ping() -{ - char buf[10]; - size_t len; - -#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE - /* - * QSocketNotifier cannot be used with Windows named pipes, so use a - * timer to check for received messages for now. This could be - * optimized be doing something specific to named pipes or Windows - * events, but it is not clear what would be the best way of doing that - * in Qt. - */ - receiveMsgs(); -#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ - - if (scanres && !scanres->isVisible()) { - delete scanres; - scanres = NULL; - } - - if (eh && !eh->isVisible()) { - delete eh; - eh = NULL; - } - - if (udr && !udr->isVisible()) { - delete udr; - udr = NULL; - } - - len = sizeof(buf) - 1; - if (ctrlRequest("PING", buf, &len) < 0) { - printf("PING failed - trying to reconnect\n"); - if (openCtrlConnection(ctrl_iface) >= 0) { - printf("Reconnected successfully\n"); - pingsToStatusUpdate = 0; - } - } - - pingsToStatusUpdate--; - if (pingsToStatusUpdate <= 0) { - updateStatus(); - updateNetworks(); - } -} - - -static int str_match(const char *a, const char *b) -{ - return strncmp(a, b, strlen(b)) == 0; -} - - -void WpaGui::processMsg(char *msg) -{ - char *pos = msg, *pos2; - int priority = 2; - - if (*pos == '<') { - /* skip priority */ - pos++; - priority = atoi(pos); - pos = strchr(pos, '>'); - if (pos) - pos++; - else - pos = msg; - } - - WpaMsg wm(pos, priority); - if (eh) - eh->addEvent(wm); - msgs.append(wm); - while (msgs.count() > 100) - msgs.pop_front(); - - /* Update last message with truncated version of the event */ - if (strncmp(pos, "CTRL-", 5) == 0) { - pos2 = strchr(pos, str_match(pos, WPA_CTRL_REQ) ? ':' : ' '); - if (pos2) - pos2++; - else - pos2 = pos; - } else - pos2 = pos; - QString lastmsg = pos2; - lastmsg.truncate(40); - textLastMessage->setText(lastmsg); - - pingsToStatusUpdate = 0; - networkMayHaveChanged = true; - - if (str_match(pos, WPA_CTRL_REQ)) - processCtrlReq(pos + strlen(WPA_CTRL_REQ)); -} - - -void WpaGui::processCtrlReq(const char *req) -{ - if (udr) { - udr->close(); - delete udr; - } - udr = new UserDataRequest(); - if (udr == NULL) - return; - if (udr->setParams(this, req) < 0) { - delete udr; - udr = NULL; - return; - } - udr->show(); - udr->exec(); -} - - -void WpaGui::receiveMsgs() -{ - char buf[256]; - size_t len; - - while (monitor_conn && wpa_ctrl_pending(monitor_conn) > 0) { - len = sizeof(buf) - 1; - if (wpa_ctrl_recv(monitor_conn, buf, &len) == 0) { - buf[len] = '\0'; - processMsg(buf); - } - } -} - - -void WpaGui::connectB() -{ - char reply[10]; - size_t reply_len = sizeof(reply); - ctrlRequest("REASSOCIATE", reply, &reply_len); -} - - -void WpaGui::selectNetwork( const QString &sel ) -{ - QString cmd(sel); - char reply[10]; - size_t reply_len = sizeof(reply); - - int pos = cmd.find(':'); - if (pos < 0) { - printf("Invalid selectNetwork '%s'\n", cmd.ascii()); - return; - } - cmd.truncate(pos); - cmd.prepend("SELECT_NETWORK "); - ctrlRequest(cmd.ascii(), reply, &reply_len); -} - - -void WpaGui::editNetwork() -{ - QString sel(networkSelect->currentText()); - int pos = sel.find(':'); - if (pos < 0) { - printf("Invalid selectNetwork '%s'\n", sel.ascii()); - return; - } - sel.truncate(pos); - - NetworkConfig *nc = new NetworkConfig(); - if (nc == NULL) - return; - nc->setWpaGui(this); - - nc->paramsFromConfig(sel.toInt()); - nc->show(); - nc->exec(); -} - - -void WpaGui::triggerUpdate() -{ - updateStatus(); - networkMayHaveChanged = true; - updateNetworks(); -} - - -void WpaGui::addNetwork() -{ - NetworkConfig *nc = new NetworkConfig(); - if (nc == NULL) - return; - nc->setWpaGui(this); - nc->newNetwork(); - nc->show(); - nc->exec(); -} - - -void WpaGui::selectAdapter( const QString & sel ) -{ - if (openCtrlConnection(sel.ascii()) < 0) - printf("Failed to open control connection to " - "wpa_supplicant.\n"); - updateStatus(); - updateNetworks(); -} diff --git a/contrib/wpa_supplicant/wpa_gui-qt4/wpagui.h b/contrib/wpa_supplicant/wpa_gui-qt4/wpagui.h deleted file mode 100644 index cd5c1afa4463..000000000000 --- a/contrib/wpa_supplicant/wpa_gui-qt4/wpagui.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * wpa_gui - WpaGui class - * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 WPAGUI_H -#define WPAGUI_H - -#include <QObject> -#include "ui_wpagui.h" - -class UserDataRequest; - - -class WpaGui : public QMainWindow, public Ui::WpaGui -{ - Q_OBJECT - -public: - WpaGui(QWidget *parent = 0, const char *name = 0, - Qt::WFlags fl = Qt::WType_TopLevel); - ~WpaGui(); - - virtual int ctrlRequest(const char *cmd, char *buf, size_t *buflen); - virtual void triggerUpdate(); - -public slots: - virtual void parse_argv(); - virtual void updateStatus(); - virtual void updateNetworks(); - virtual void helpIndex(); - virtual void helpContents(); - virtual void helpAbout(); - virtual void disconnect(); - virtual void scan(); - virtual void eventHistory(); - virtual void ping(); - virtual void processMsg(char *msg); - virtual void processCtrlReq(const char *req); - virtual void receiveMsgs(); - virtual void connectB(); - virtual void selectNetwork(const QString &sel); - virtual void editNetwork(); - virtual void addNetwork(); - virtual void selectAdapter(const QString &sel); - -protected slots: - virtual void languageChange(); - -private: - ScanResults *scanres; - bool networkMayHaveChanged; - char *ctrl_iface; - EventHistory *eh; - struct wpa_ctrl *ctrl_conn; - QSocketNotifier *msgNotifier; - QTimer *timer; - int pingsToStatusUpdate; - WpaMsgList msgs; - char *ctrl_iface_dir; - struct wpa_ctrl *monitor_conn; - UserDataRequest *udr; - - int openCtrlConnection(const char *ifname); -}; - -#endif /* WPAGUI_H */ diff --git a/contrib/wpa_supplicant/wpa_gui-qt4/wpagui.ui b/contrib/wpa_supplicant/wpa_gui-qt4/wpagui.ui deleted file mode 100644 index 7047a2a106fc..000000000000 --- a/contrib/wpa_supplicant/wpa_gui-qt4/wpagui.ui +++ /dev/null @@ -1,318 +0,0 @@ -<ui version="4.0" stdsetdef="1" > - <author></author> - <comment></comment> - <exportmacro></exportmacro> - <class>WpaGui</class> - <widget class="QMainWindow" name="WpaGui" > - <property name="geometry" > - <rect> - <x>0</x> - <y>0</y> - <width>279</width> - <height>308</height> - </rect> - </property> - <property name="windowTitle" > - <string>wpa_gui</string> - </property> - <widget class="QWidget" > - <layout class="QGridLayout" > - <item rowspan="1" row="0" column="0" colspan="2" > - <widget class="QLabel" name="textLabel16" > - <property name="text" > - <string>Adapter:</string> - </property> - </widget> - </item> - <item rowspan="1" row="0" column="2" colspan="2" > - <widget class="QComboBox" name="adapterSelect" /> - </item> - <item rowspan="1" row="1" column="0" colspan="2" > - <widget class="QLabel" name="textLabel8" > - <property name="text" > - <string>Network:</string> - </property> - </widget> - </item> - <item rowspan="1" row="1" column="2" colspan="2" > - <widget class="QComboBox" name="networkSelect" /> - </item> - <item rowspan="1" row="2" column="0" colspan="4" > - <widget class="QFrame" name="frame3" > - <property name="frameShape" > - <enum>StyledPanel</enum> - </property> - <property name="frameShadow" > - <enum>Raised</enum> - </property> - <layout class="QGridLayout" > - <item row="0" column="0" > - <widget class="QLabel" name="textLabel1" > - <property name="text" > - <string>Status:</string> - </property> - </widget> - </item> - <item row="1" column="0" > - <widget class="QLabel" name="textLabel2" > - <property name="text" > - <string>Last message:</string> - </property> - </widget> - </item> - <item row="2" column="0" > - <widget class="QLabel" name="textLabel3" > - <property name="text" > - <string>Authentication:</string> - </property> - </widget> - </item> - <item row="3" column="0" > - <widget class="QLabel" name="textLabel4" > - <property name="text" > - <string>Encryption:</string> - </property> - </widget> - </item> - <item row="4" column="0" > - <widget class="QLabel" name="textLabel5" > - <property name="text" > - <string>SSID:</string> - </property> - </widget> - </item> - <item row="5" column="0" > - <widget class="QLabel" name="textLabel6" > - <property name="text" > - <string>BSSID:</string> - </property> - </widget> - </item> - <item row="6" column="0" > - <widget class="QLabel" name="textLabel7" > - <property name="text" > - <string>IP address:</string> - </property> - </widget> - </item> - <item row="0" column="1" > - <widget class="QLabel" name="textStatus" > - <property name="text" > - <string/> - </property> - </widget> - </item> - <item rowspan="1" row="1" column="1" colspan="3" > - <widget class="QLabel" name="textLastMessage" > - <property name="text" > - <string/> - </property> - </widget> - </item> - <item row="2" column="1" > - <widget class="QLabel" name="textAuthentication" > - <property name="text" > - <string/> - </property> - </widget> - </item> - <item row="3" column="1" > - <widget class="QLabel" name="textEncryption" > - <property name="text" > - <string/> - </property> - </widget> - </item> - <item row="4" column="1" > - <widget class="QLabel" name="textSsid" > - <property name="text" > - <string/> - </property> - </widget> - </item> - <item row="5" column="1" > - <widget class="QLabel" name="textBssid" > - <property name="text" > - <string/> - </property> - </widget> - </item> - <item row="6" column="1" > - <widget class="QLabel" name="textIpAddress" > - <property name="text" > - <string/> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item row="3" column="0" > - <spacer name="spacer7" > - <property name="sizeHint" > - <size> - <width>16</width> - <height>16</height> - </size> - </property> - <property name="sizeType" > - <enum>Expanding</enum> - </property> - <property name="orientation" > - <enum>Horizontal</enum> - </property> - </spacer> - </item> - <item row="3" column="1" > - <widget class="QPushButton" name="connectButton" > - <property name="text" > - <string>Connect</string> - </property> - </widget> - </item> - <item row="3" column="2" > - <widget class="QPushButton" name="disconnectButton" > - <property name="text" > - <string>Disconnect</string> - </property> - </widget> - </item> - <item row="3" column="3" > - <widget class="QPushButton" name="scanButton" > - <property name="text" > - <string>Scan</string> - </property> - </widget> - </item> - </layout> - </widget> - <widget class="QMenuBar" name="MenuBar" > - <widget class="QMenu" name="fileMenu" > - <property name="title" > - <string>&File</string> - </property> - <addaction name="separator" /> - <addaction name="fileEventHistoryAction" /> - <addaction name="fileAdd_NetworkAction" /> - <addaction name="fileEdit_networkAction" /> - <addaction name="separator" /> - <addaction name="fileExitAction" /> - </widget> - <widget class="QMenu" name="helpMenu" > - <property name="title" > - <string>&Help</string> - </property> - <addaction name="helpContentsAction" /> - <addaction name="helpIndexAction" /> - <addaction name="separator" /> - <addaction name="helpAboutAction" /> - </widget> - <addaction name="fileMenu" /> - <addaction name="helpMenu" /> - </widget> - <action name="fileExitAction" > - <property name="name" > - <cstring>fileExitAction</cstring> - </property> - <property name="iconText" > - <string>Exit</string> - </property> - <property name="text" > - <string>E&xit</string> - </property> - <property name="shortcut" > - <string>Ctrl+Q</string> - </property> - </action> - <action name="helpContentsAction" > - <property name="name" > - <cstring>helpContentsAction</cstring> - </property> - <property name="enabled" > - <bool>false</bool> - </property> - <property name="iconText" > - <string>Contents</string> - </property> - <property name="text" > - <string>&Contents...</string> - </property> - <property name="shortcut" > - <string/> - </property> - </action> - <action name="helpIndexAction" > - <property name="name" > - <cstring>helpIndexAction</cstring> - </property> - <property name="enabled" > - <bool>false</bool> - </property> - <property name="iconText" > - <string>Index</string> - </property> - <property name="text" > - <string>&Index...</string> - </property> - <property name="shortcut" > - <string/> - </property> - </action> - <action name="helpAboutAction" > - <property name="name" > - <cstring>helpAboutAction</cstring> - </property> - <property name="iconText" > - <string>About</string> - </property> - <property name="text" > - <string>&About</string> - </property> - <property name="shortcut" > - <string/> - </property> - </action> - <action name="fileEventHistoryAction" > - <property name="name" > - <cstring>fileEventHistoryAction</cstring> - </property> - <property name="iconText" > - <string>Event History</string> - </property> - <property name="text" > - <string>Event &History</string> - </property> - </action> - <action name="fileAdd_NetworkAction" > - <property name="name" > - <cstring>fileAdd_NetworkAction</cstring> - </property> - <property name="iconText" > - <string>Add Network</string> - </property> - <property name="text" > - <string>&Add Network</string> - </property> - </action> - <action name="fileEdit_networkAction" > - <property name="name" > - <cstring>fileEdit_networkAction</cstring> - </property> - <property name="iconText" > - <string>Edit Network</string> - </property> - <property name="text" > - <string>&Edit Network</string> - </property> - </action> - </widget> - <layoutdefault spacing="6" margin="11" /> - <pixmapfunction>qPixmapFromMimeSource</pixmapfunction> - <includes> - <include location="global" >qtimer.h</include> - <include location="global" >qsocketnotifier.h</include> - <include location="local" >wpamsg.h</include> - <include location="local" >eventhistory.h</include> - <include location="local" >scanresults.h</include> - </includes> -</ui> diff --git a/contrib/wpa_supplicant/wpa_gui-qt4/wpamsg.h b/contrib/wpa_supplicant/wpa_gui-qt4/wpamsg.h deleted file mode 100644 index 65ce2e884414..000000000000 --- a/contrib/wpa_supplicant/wpa_gui-qt4/wpamsg.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * wpa_gui - WpaMsg class for storing event messages - * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 WPAMSG_H -#define WPAMSG_H - -#include <QDateTime> -#include <QLinkedList> - -class WpaMsg { -public: - WpaMsg() {} - WpaMsg(const QString &_msg, int _priority = 2) - : msg(_msg), priority(_priority) - { - timestamp = QDateTime::currentDateTime(); - } - - QString getMsg() const { return msg; } - int getPriority() const { return priority; } - QDateTime getTimestamp() const { return timestamp; } - -private: - QString msg; - int priority; - QDateTime timestamp; -}; - -typedef QLinkedList<WpaMsg> WpaMsgList; - -#endif /* WPAMSG_H */ diff --git a/contrib/wpa_supplicant/wpa_gui/eventhistory.ui b/contrib/wpa_supplicant/wpa_gui/eventhistory.ui deleted file mode 100644 index 3735fb70e8f9..000000000000 --- a/contrib/wpa_supplicant/wpa_gui/eventhistory.ui +++ /dev/null @@ -1,125 +0,0 @@ -<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> -<class>EventHistory</class> -<widget class="QDialog"> - <property name="name"> - <cstring>EventHistory</cstring> - </property> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>533</width> - <height>285</height> - </rect> - </property> - <property name="caption"> - <string>Event history</string> - </property> - <vbox> - <property name="name"> - <cstring>unnamed</cstring> - </property> - <widget class="QListView"> - <column> - <property name="text"> - <string>Timestamp</string> - </property> - <property name="clickable"> - <bool>true</bool> - </property> - <property name="resizable"> - <bool>true</bool> - </property> - </column> - <column> - <property name="text"> - <string>Message</string> - </property> - <property name="clickable"> - <bool>true</bool> - </property> - <property name="resizable"> - <bool>true</bool> - </property> - </column> - <property name="name"> - <cstring>eventListView</cstring> - </property> - <property name="sizePolicy"> - <sizepolicy> - <hsizetype>7</hsizetype> - <vsizetype>7</vsizetype> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="resizePolicy"> - <enum>Manual</enum> - </property> - <property name="selectionMode"> - <enum>NoSelection</enum> - </property> - <property name="resizeMode"> - <enum>LastColumn</enum> - </property> - </widget> - <widget class="QLayoutWidget"> - <property name="name"> - <cstring>layout30</cstring> - </property> - <hbox> - <property name="name"> - <cstring>unnamed</cstring> - </property> - <spacer> - <property name="name"> - <cstring>spacer3</cstring> - </property> - <property name="orientation"> - <enum>Horizontal</enum> - </property> - <property name="sizeType"> - <enum>Expanding</enum> - </property> - <property name="sizeHint"> - <size> - <width>20</width> - <height>20</height> - </size> - </property> - </spacer> - <widget class="QPushButton"> - <property name="name"> - <cstring>closeButton</cstring> - </property> - <property name="text"> - <string>Close</string> - </property> - </widget> - </hbox> - </widget> - </vbox> -</widget> -<connections> - <connection> - <sender>closeButton</sender> - <signal>clicked()</signal> - <receiver>EventHistory</receiver> - <slot>close()</slot> - </connection> -</connections> -<includes> - <include location="local" impldecl="in declaration">wpamsg.h</include> - <include location="local" impldecl="in implementation">eventhistory.ui.h</include> -</includes> -<slots> - <slot>addEvents( WpaMsgList msgs )</slot> - <slot>addEvent( WpaMsg msg )</slot> -</slots> -<functions> - <function access="private" specifier="non virtual">init()</function> - <function access="private" specifier="non virtual">destroy()</function> -</functions> -<pixmapinproject/> -<layoutdefaults spacing="6" margin="11"/> -</UI> diff --git a/contrib/wpa_supplicant/wpa_gui/eventhistory.ui.h b/contrib/wpa_supplicant/wpa_gui/eventhistory.ui.h deleted file mode 100644 index cb2caab2e4e1..000000000000 --- a/contrib/wpa_supplicant/wpa_gui/eventhistory.ui.h +++ /dev/null @@ -1,41 +0,0 @@ -/**************************************************************************** -** ui.h extension file, included from the uic-generated form implementation. -** -** If you want to add, delete, or rename functions or slots, use -** Qt Designer to update this file, preserving your code. -** -** You should not define a constructor or destructor in this file. -** Instead, write your code in functions called init() and destroy(). -** These will automatically be called by the form's constructor and -** destructor. -*****************************************************************************/ - -void EventHistory::init() -{ -} - - -void EventHistory::destroy() -{ -} - - -void EventHistory::addEvents(WpaMsgList msgs) -{ - WpaMsgList::iterator it; - for (it = msgs.begin(); it != msgs.end(); it++) { - addEvent(*it); - } -} - - -void EventHistory::addEvent(WpaMsg msg) -{ - Q3ListViewItem *item; - item = new Q3ListViewItem(eventListView, - msg.getTimestamp().toString("yyyy-MM-dd hh:mm:ss.zzz"), - msg.getMsg()); - if (item == NULL) - return; - eventListView->setSelected(item, false); -} diff --git a/contrib/wpa_supplicant/wpa_gui/main.cpp b/contrib/wpa_supplicant/wpa_gui/main.cpp deleted file mode 100644 index a78473a8c6b1..000000000000 --- a/contrib/wpa_supplicant/wpa_gui/main.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#ifdef CONFIG_NATIVE_WINDOWS -#include <winsock.h> -#endif /* CONFIG_NATIVE_WINDOWS */ -#include <qapplication.h> -#include "wpagui.h" - -int main( int argc, char ** argv ) -{ - QApplication a( argc, argv ); - WpaGui w; - int ret; - -#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 */ - - w.show(); - a.connect( &a, SIGNAL( lastWindowClosed() ), &a, SLOT( quit() ) ); - ret = a.exec(); - -#ifdef CONFIG_NATIVE_WINDOWS - WSACleanup(); -#endif /* CONFIG_NATIVE_WINDOWS */ - - return ret; -} diff --git a/contrib/wpa_supplicant/wpa_gui/networkconfig.ui b/contrib/wpa_supplicant/wpa_gui/networkconfig.ui deleted file mode 100644 index 1f98372f5cd9..000000000000 --- a/contrib/wpa_supplicant/wpa_gui/networkconfig.ui +++ /dev/null @@ -1,455 +0,0 @@ -<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> -<class>NetworkConfig</class> -<widget class="QDialog"> - <property name="name"> - <cstring>NetworkConfig</cstring> - </property> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>380</width> - <height>413</height> - </rect> - </property> - <property name="caption"> - <string>NetworkConfig</string> - </property> - <grid> - <property name="name"> - <cstring>unnamed</cstring> - </property> - <widget class="QPushButton" row="1" column="3"> - <property name="name"> - <cstring>cancelButton</cstring> - </property> - <property name="text"> - <string>Cancel</string> - </property> - </widget> - <widget class="QFrame" row="0" column="0" rowspan="1" colspan="4"> - <property name="name"> - <cstring>frame9</cstring> - </property> - <property name="frameShape"> - <enum>StyledPanel</enum> - </property> - <property name="frameShadow"> - <enum>Raised</enum> - </property> - <grid> - <property name="name"> - <cstring>unnamed</cstring> - </property> - <widget class="QLabel" row="0" column="0"> - <property name="name"> - <cstring>textLabel1</cstring> - </property> - <property name="text"> - <string>SSID</string> - </property> - </widget> - <widget class="QLineEdit" row="0" column="1"> - <property name="name"> - <cstring>ssidEdit</cstring> - </property> - <property name="text"> - <string></string> - </property> - <property name="toolTip" stdset="0"> - <string>Network name (Service Set IDentifier)</string> - </property> - </widget> - <widget class="QLabel" row="1" column="0"> - <property name="name"> - <cstring>textLabel2</cstring> - </property> - <property name="text"> - <string>Authentication</string> - </property> - </widget> - <widget class="QComboBox" row="1" column="1"> - <item> - <property name="text"> - <string>Plaintext or static WEP</string> - </property> - </item> - <item> - <property name="text"> - <string>IEEE 802.1X</string> - </property> - </item> - <item> - <property name="text"> - <string>WPA-Personal (PSK)</string> - </property> - </item> - <item> - <property name="text"> - <string>WPA-Enterprise (EAP)</string> - </property> - </item> - <item> - <property name="text"> - <string>WPA2-Personal (PSK)</string> - </property> - </item> - <item> - <property name="text"> - <string>WPA2-Enterprise (EAP)</string> - </property> - </item> - <property name="name"> - <cstring>authSelect</cstring> - </property> - </widget> - <widget class="QLabel" row="2" column="0"> - <property name="name"> - <cstring>textLabel3</cstring> - </property> - <property name="text"> - <string>Encryption</string> - </property> - </widget> - <widget class="QComboBox" row="2" column="1"> - <item> - <property name="text"> - <string>None</string> - </property> - </item> - <item> - <property name="text"> - <string>WEP</string> - </property> - </item> - <item> - <property name="text"> - <string>TKIP</string> - </property> - </item> - <item> - <property name="text"> - <string>CCMP</string> - </property> - </item> - <property name="name"> - <cstring>encrSelect</cstring> - </property> - </widget> - <widget class="QLabel" row="3" column="0"> - <property name="name"> - <cstring>textLabel4</cstring> - </property> - <property name="text"> - <string>PSK</string> - </property> - </widget> - <widget class="QLineEdit" row="3" column="1"> - <property name="name"> - <cstring>pskEdit</cstring> - </property> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="echoMode"> - <enum>Password</enum> - </property> - <property name="toolTip" stdset="0"> - <string>WPA/WPA2 pre-shared key or passphrase</string> - </property> - <property name="whatsThis" stdset="0"> - <string></string> - </property> - </widget> - <widget class="QLabel" row="4" column="0"> - <property name="name"> - <cstring>textLabel5</cstring> - </property> - <property name="text"> - <string>EAP method</string> - </property> - </widget> - <widget class="QComboBox" row="4" column="1"> - <property name="name"> - <cstring>eapSelect</cstring> - </property> - <property name="enabled"> - <bool>false</bool> - </property> - </widget> - <widget class="QLabel" row="5" column="0"> - <property name="name"> - <cstring>textLabel6</cstring> - </property> - <property name="text"> - <string>Identity</string> - </property> - </widget> - <widget class="QLineEdit" row="5" column="1"> - <property name="name"> - <cstring>identityEdit</cstring> - </property> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="toolTip" stdset="0"> - <string>Username/Identity for EAP methods</string> - </property> - </widget> - <widget class="QLabel" row="6" column="0"> - <property name="name"> - <cstring>textLabel7</cstring> - </property> - <property name="text"> - <string>Password</string> - </property> - </widget> - <widget class="QLineEdit" row="6" column="1"> - <property name="name"> - <cstring>passwordEdit</cstring> - </property> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="echoMode"> - <enum>Password</enum> - </property> - <property name="toolTip" stdset="0"> - <string>Password for EAP methods</string> - </property> - </widget> - <widget class="QLabel" row="7" column="0"> - <property name="name"> - <cstring>textLabel1_2</cstring> - </property> - <property name="text"> - <string>CA certificate</string> - </property> - </widget> - <widget class="QLineEdit" row="7" column="1"> - <property name="name"> - <cstring>cacertEdit</cstring> - </property> - <property name="enabled"> - <bool>false</bool> - </property> - </widget> - <widget class="QButtonGroup" row="8" column="0" rowspan="1" colspan="2"> - <property name="name"> - <cstring>buttonGroup1</cstring> - </property> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="title"> - <string>WEP keys</string> - </property> - <grid> - <property name="name"> - <cstring>unnamed</cstring> - </property> - <widget class="QRadioButton" row="0" column="0"> - <property name="name"> - <cstring>wep0Radio</cstring> - </property> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>key 0</string> - </property> - </widget> - <widget class="QRadioButton" row="1" column="0"> - <property name="name"> - <cstring>wep1Radio</cstring> - </property> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>key 1</string> - </property> - </widget> - <widget class="QRadioButton" row="3" column="0"> - <property name="name"> - <cstring>wep3Radio</cstring> - </property> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>key 3</string> - </property> - </widget> - <widget class="QRadioButton" row="2" column="0"> - <property name="name"> - <cstring>wep2Radio</cstring> - </property> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>key 2</string> - </property> - </widget> - <widget class="QLineEdit" row="0" column="1"> - <property name="name"> - <cstring>wep0Edit</cstring> - </property> - <property name="enabled"> - <bool>false</bool> - </property> - </widget> - <widget class="QLineEdit" row="1" column="1"> - <property name="name"> - <cstring>wep1Edit</cstring> - </property> - <property name="enabled"> - <bool>false</bool> - </property> - </widget> - <widget class="QLineEdit" row="2" column="1"> - <property name="name"> - <cstring>wep2Edit</cstring> - </property> - <property name="enabled"> - <bool>false</bool> - </property> - </widget> - <widget class="QLineEdit" row="3" column="1"> - <property name="name"> - <cstring>wep3Edit</cstring> - </property> - <property name="enabled"> - <bool>false</bool> - </property> - </widget> - </grid> - </widget> - </grid> - </widget> - <spacer row="1" column="0"> - <property name="name"> - <cstring>spacer5</cstring> - </property> - <property name="orientation"> - <enum>Horizontal</enum> - </property> - <property name="sizeType"> - <enum>Expanding</enum> - </property> - <property name="sizeHint"> - <size> - <width>130</width> - <height>20</height> - </size> - </property> - </spacer> - <widget class="QPushButton" row="1" column="1"> - <property name="name"> - <cstring>addButton</cstring> - </property> - <property name="text"> - <string>Add</string> - </property> - </widget> - <widget class="QPushButton" row="1" column="2"> - <property name="name"> - <cstring>removeButton</cstring> - </property> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Remove</string> - </property> - </widget> - </grid> -</widget> -<connections> - <connection> - <sender>authSelect</sender> - <signal>activated(int)</signal> - <receiver>NetworkConfig</receiver> - <slot>authChanged(int)</slot> - </connection> - <connection> - <sender>cancelButton</sender> - <signal>clicked()</signal> - <receiver>NetworkConfig</receiver> - <slot>close()</slot> - </connection> - <connection> - <sender>addButton</sender> - <signal>clicked()</signal> - <receiver>NetworkConfig</receiver> - <slot>addNetwork()</slot> - </connection> - <connection> - <sender>encrSelect</sender> - <signal>activated(const QString&)</signal> - <receiver>NetworkConfig</receiver> - <slot>encrChanged(const QString&)</slot> - </connection> - <connection> - <sender>removeButton</sender> - <signal>clicked()</signal> - <receiver>NetworkConfig</receiver> - <slot>removeNetwork()</slot> - </connection> -</connections> -<tabstops> - <tabstop>ssidEdit</tabstop> - <tabstop>authSelect</tabstop> - <tabstop>encrSelect</tabstop> - <tabstop>pskEdit</tabstop> - <tabstop>eapSelect</tabstop> - <tabstop>identityEdit</tabstop> - <tabstop>passwordEdit</tabstop> - <tabstop>cacertEdit</tabstop> - <tabstop>wep0Radio</tabstop> - <tabstop>wep1Radio</tabstop> - <tabstop>wep2Radio</tabstop> - <tabstop>wep3Radio</tabstop> - <tabstop>wep0Edit</tabstop> - <tabstop>wep1Edit</tabstop> - <tabstop>wep2Edit</tabstop> - <tabstop>wep3Edit</tabstop> - <tabstop>addButton</tabstop> - <tabstop>removeButton</tabstop> - <tabstop>cancelButton</tabstop> -</tabstops> -<includes> - <include location="global" impldecl="in declaration">qlistview.h</include> - <include location="global" impldecl="in implementation">qmessagebox.h</include> - <include location="local" impldecl="in implementation">wpagui.h</include> - <include location="local" impldecl="in implementation">networkconfig.ui.h</include> -</includes> -<forwards> - <forward>class WpaGui;</forward> -</forwards> -<variables> - <variable access="private">WpaGui *wpagui;</variable> - <variable access="private">int edit_network_id;</variable> - <variable access="private">bool new_network;</variable> -</variables> -<slots> - <slot>authChanged( int sel )</slot> - <slot>addNetwork()</slot> - <slot>encrChanged( const QString & sel )</slot> - <slot>writeWepKey( int network_id, QLineEdit * edit, int id )</slot> - <slot>removeNetwork()</slot> -</slots> -<functions> - <function access="private" specifier="non virtual">init()</function> - <function>paramsFromScanResults( QListViewItem * sel )</function> - <function>setWpaGui( WpaGui * _wpagui )</function> - <function returnType="int">setNetworkParam( int id, const char * field, const char * value, bool quote )</function> - <function access="private">wepEnabled( bool enabled )</function> - <function>paramsFromConfig( int network_id )</function> - <function>newNetwork()</function> - <function access="private">getEapCapa()</function> -</functions> -<pixmapinproject/> -<layoutdefaults spacing="6" margin="11"/> -</UI> diff --git a/contrib/wpa_supplicant/wpa_gui/networkconfig.ui.h b/contrib/wpa_supplicant/wpa_gui/networkconfig.ui.h deleted file mode 100644 index 22afed9b316c..000000000000 --- a/contrib/wpa_supplicant/wpa_gui/networkconfig.ui.h +++ /dev/null @@ -1,538 +0,0 @@ -/**************************************************************************** -** ui.h extension file, included from the uic-generated form implementation. -** -** If you want to add, delete, or rename functions or slots, use -** Qt Designer to update this file, preserving your code. -** -** You should not define a constructor or destructor in this file. -** Instead, write your code in functions called init() and destroy(). -** These will automatically be called by the form's constructor and -** destructor. -*****************************************************************************/ - -#include <stdlib.h> - -enum { - AUTH_NONE = 0, - AUTH_IEEE8021X = 1, - AUTH_WPA_PSK = 2, - AUTH_WPA_EAP = 3, - AUTH_WPA2_PSK = 4, - AUTH_WPA2_EAP = 5 -}; - -#define WPA_GUI_KEY_DATA "[key is configured]" - -void NetworkConfig::init() -{ - wpagui = NULL; - new_network = false; -} - -void NetworkConfig::paramsFromScanResults(Q3ListViewItem *sel) -{ - new_network = true; - - /* SSID BSSID frequency signal flags */ - setCaption(sel->text(0)); - ssidEdit->setText(sel->text(0)); - - QString flags = sel->text(4); - int auth, encr = 0; - if (flags.find("[WPA2-EAP") >= 0) - auth = AUTH_WPA2_EAP; - else if (flags.find("[WPA-EAP") >= 0) - auth = AUTH_WPA_EAP; - else if (flags.find("[WPA2-PSK") >= 0) - auth = AUTH_WPA2_PSK; - else if (flags.find("[WPA-PSK") >= 0) - auth = AUTH_WPA_PSK; - else - auth = AUTH_NONE; - - if (flags.find("-CCMP") >= 0) - encr = 1; - else if (flags.find("-TKIP") >= 0) - encr = 0; - else if (flags.find("WEP") >= 0) - encr = 1; - else - encr = 0; - - authSelect->setCurrentItem(auth); - authChanged(auth); - encrSelect->setCurrentItem(encr); - - getEapCapa(); -} - - -void NetworkConfig::authChanged(int sel) -{ - pskEdit->setEnabled(sel == AUTH_WPA_PSK || sel == AUTH_WPA2_PSK); - bool eap = sel == AUTH_IEEE8021X || sel == AUTH_WPA_EAP || - sel == AUTH_WPA2_EAP; - eapSelect->setEnabled(eap); - identityEdit->setEnabled(eap); - passwordEdit->setEnabled(eap); - cacertEdit->setEnabled(eap); - - while (encrSelect->count()) - encrSelect->removeItem(0); - - if (sel == AUTH_NONE || sel == AUTH_IEEE8021X) { - encrSelect->insertItem("None"); - encrSelect->insertItem("WEP"); - encrSelect->setCurrentItem(sel == AUTH_NONE ? 0 : 1); - } else { - encrSelect->insertItem("TKIP"); - encrSelect->insertItem("CCMP"); - encrSelect->setCurrentItem((sel == AUTH_WPA2_PSK || - sel == AUTH_WPA2_EAP) ? 1 : 0); - } - - wepEnabled(sel == AUTH_IEEE8021X); -} - - -void NetworkConfig::addNetwork() -{ - char reply[10], cmd[256]; - size_t reply_len; - int id; - int psklen = pskEdit->text().length(); - int auth = authSelect->currentItem(); - - if (auth == AUTH_WPA_PSK || auth == AUTH_WPA2_PSK) { - if (psklen < 8 || psklen > 64) { - QMessageBox::warning(this, "wpa_gui", "WPA-PSK requires a passphrase " - "of 8 to 63 characters\n" - "or 64 hex digit PSK"); - return; - } - } - - if (wpagui == NULL) - return; - - memset(reply, 0, sizeof(reply)); - reply_len = sizeof(reply) - 1; - - if (new_network) { - wpagui->ctrlRequest("ADD_NETWORK", reply, &reply_len); - if (reply[0] == 'F') { - QMessageBox::warning(this, "wpa_gui", "Failed to add network to wpa_supplicant\n" - "configuration."); - return; - } - id = atoi(reply); - } else { - id = edit_network_id; - } - - setNetworkParam(id, "ssid", ssidEdit->text().ascii(), true); - - const char *key_mgmt = NULL, *proto = NULL, *pairwise = NULL; - switch (auth) { - case AUTH_NONE: - key_mgmt = "NONE"; - break; - case AUTH_IEEE8021X: - key_mgmt = "IEEE8021X"; - break; - case AUTH_WPA_PSK: - key_mgmt = "WPA-PSK"; - proto = "WPA"; - break; - case AUTH_WPA_EAP: - key_mgmt = "WPA-EAP"; - proto = "WPA"; - break; - case AUTH_WPA2_PSK: - key_mgmt = "WPA-PSK"; - proto = "WPA2"; - break; - case AUTH_WPA2_EAP: - key_mgmt = "WPA-EAP"; - proto = "WPA2"; - break; - } - - if (auth == AUTH_WPA_PSK || auth == AUTH_WPA_EAP || - auth == AUTH_WPA2_PSK || auth == AUTH_WPA2_EAP) { - int encr = encrSelect->currentItem(); - if (encr == 0) - pairwise = "TKIP"; - else - pairwise = "CCMP"; - } - - if (proto) - setNetworkParam(id, "proto", proto, false); - if (key_mgmt) - setNetworkParam(id, "key_mgmt", key_mgmt, false); - if (pairwise) { - setNetworkParam(id, "pairwise", pairwise, false); - setNetworkParam(id, "group", "TKIP CCMP WEP104 WEP40", false); - } - if (pskEdit->isEnabled() && - strcmp(passwordEdit->text().ascii(), WPA_GUI_KEY_DATA) != 0) - setNetworkParam(id, "psk", pskEdit->text().ascii(), psklen != 64); - if (eapSelect->isEnabled()) - setNetworkParam(id, "eap", eapSelect->currentText().ascii(), false); - if (identityEdit->isEnabled()) - setNetworkParam(id, "identity", identityEdit->text().ascii(), true); - if (passwordEdit->isEnabled() && - strcmp(passwordEdit->text().ascii(), WPA_GUI_KEY_DATA) != 0) - setNetworkParam(id, "password", passwordEdit->text().ascii(), true); - if (cacertEdit->isEnabled()) - setNetworkParam(id, "ca_cert", cacertEdit->text().ascii(), true); - writeWepKey(id, wep0Edit, 0); - writeWepKey(id, wep1Edit, 1); - writeWepKey(id, wep2Edit, 2); - writeWepKey(id, wep3Edit, 3); - - if (wep0Radio->isEnabled() && wep0Radio->isChecked()) - setNetworkParam(id, "wep_tx_keyidx", "0", false); - else if (wep1Radio->isEnabled() && wep1Radio->isChecked()) - setNetworkParam(id, "wep_tx_keyidx", "1", false); - else if (wep2Radio->isEnabled() && wep2Radio->isChecked()) - setNetworkParam(id, "wep_tx_keyidx", "2", false); - else if (wep3Radio->isEnabled() && wep3Radio->isChecked()) - setNetworkParam(id, "wep_tx_keyidx", "3", false); - - snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %d", id); - reply_len = sizeof(reply); - wpagui->ctrlRequest(cmd, reply, &reply_len); - if (strncmp(reply, "OK", 2) != 0) { - QMessageBox::warning(this, "wpa_gui", "Failed to enable network in wpa_supplicant\n" - "configuration."); - /* Network was added, so continue anyway */ - } - wpagui->triggerUpdate(); - wpagui->ctrlRequest("SAVE_CONFIG", reply, &reply_len); - - close(); -} - - -void NetworkConfig::setWpaGui( WpaGui *_wpagui ) -{ - wpagui = _wpagui; -} - - -int NetworkConfig::setNetworkParam(int id, const char *field, const char *value, bool quote) -{ - char reply[10], cmd[256]; - size_t reply_len; - snprintf(cmd, sizeof(cmd), "SET_NETWORK %d %s %s%s%s", - id, field, quote ? "\"" : "", value, quote ? "\"" : ""); - reply_len = sizeof(reply); - wpagui->ctrlRequest(cmd, reply, &reply_len); - return strncmp(reply, "OK", 2) == 0 ? 0 : -1; -} - - -void NetworkConfig::encrChanged( const QString &sel ) -{ - wepEnabled(sel.find("WEP") == 0); -} - - -void NetworkConfig::wepEnabled( bool enabled ) -{ - wep0Edit->setEnabled(enabled); - wep1Edit->setEnabled(enabled); - wep2Edit->setEnabled(enabled); - wep3Edit->setEnabled(enabled); - wep0Radio->setEnabled(enabled); - wep1Radio->setEnabled(enabled); - wep2Radio->setEnabled(enabled); - wep3Radio->setEnabled(enabled); -} - - -void NetworkConfig::writeWepKey( int network_id, QLineEdit *edit, int id ) -{ - char buf[10]; - bool hex; - const char *txt, *pos; - size_t len; - - if (!edit->isEnabled() || edit->text().isEmpty()) - return; - - /* - * Assume hex key if only hex characters are present and length matches - * with 40, 104, or 128-bit key - */ - txt = edit->text().ascii(); - if (strcmp(txt, WPA_GUI_KEY_DATA) == 0) - return; - len = strlen(txt); - if (len == 0) - return; - pos = txt; - hex = true; - while (*pos) { - if (!((*pos >= '0' && *pos <= '9') || (*pos >= 'a' && *pos <= 'f') || - (*pos >= 'A' && *pos <= 'F'))) { - hex = false; - break; - } - pos++; - } - if (hex && len != 10 && len != 26 && len != 32) - hex = false; - snprintf(buf, sizeof(buf), "wep_key%d", id); - setNetworkParam(network_id, buf, txt, !hex); -} - - -static int key_value_isset(const char *reply, size_t reply_len) -{ - return reply_len > 0 && (reply_len < 4 || memcmp(reply, "FAIL", 4) != 0); -} - - -void NetworkConfig::paramsFromConfig( int network_id ) -{ - int i, res; - - edit_network_id = network_id; - getEapCapa(); - - char reply[1024], cmd[256], *pos; - size_t reply_len; - - snprintf(cmd, sizeof(cmd), "GET_NETWORK %d ssid", network_id); - reply_len = sizeof(reply) - 1; - if (wpagui->ctrlRequest(cmd, reply, &reply_len) >= 0 && reply_len >= 2 && - reply[0] == '"') { - reply[reply_len] = '\0'; - pos = strchr(reply + 1, '"'); - if (pos) - *pos = '\0'; - ssidEdit->setText(reply + 1); - } - - snprintf(cmd, sizeof(cmd), "GET_NETWORK %d proto", network_id); - reply_len = sizeof(reply) - 1; - int wpa = 0; - if (wpagui->ctrlRequest(cmd, reply, &reply_len) >= 0) { - reply[reply_len] = '\0'; - if (strstr(reply, "RSN") || strstr(reply, "WPA2")) - wpa = 2; - else if (strstr(reply, "WPA")) - wpa = 1; - } - - int auth = AUTH_NONE, encr = 0; - snprintf(cmd, sizeof(cmd), "GET_NETWORK %d key_mgmt", network_id); - reply_len = sizeof(reply) - 1; - if (wpagui->ctrlRequest(cmd, reply, &reply_len) >= 0) { - reply[reply_len] = '\0'; - if (strstr(reply, "WPA-EAP")) - auth = wpa & 2 ? AUTH_WPA2_EAP : AUTH_WPA_EAP; - else if (strstr(reply, "WPA-PSK")) - auth = wpa & 2 ? AUTH_WPA2_PSK : AUTH_WPA_PSK; - else if (strstr(reply, "IEEE8021X")) { - auth = AUTH_IEEE8021X; - encr = 1; - } - } - - snprintf(cmd, sizeof(cmd), "GET_NETWORK %d pairwise", network_id); - reply_len = sizeof(reply) - 1; - if (wpagui->ctrlRequest(cmd, reply, &reply_len) >= 0) { - reply[reply_len] = '\0'; - if (strstr(reply, "CCMP")) - encr = 1; - else if (strstr(reply, "TKIP")) - encr = 0; - else if (strstr(reply, "WEP")) - encr = 1; - else - encr = 0; - } - - snprintf(cmd, sizeof(cmd), "GET_NETWORK %d psk", network_id); - reply_len = sizeof(reply) - 1; - res = wpagui->ctrlRequest(cmd, reply, &reply_len); - if (res >= 0 && reply_len >= 2 && reply[0] == '"') { - reply[reply_len] = '\0'; - pos = strchr(reply + 1, '"'); - if (pos) - *pos = '\0'; - pskEdit->setText(reply + 1); - } else if (res >= 0 && key_value_isset(reply, reply_len)) { - pskEdit->setText(WPA_GUI_KEY_DATA); - } - - snprintf(cmd, sizeof(cmd), "GET_NETWORK %d identity", network_id); - reply_len = sizeof(reply) - 1; - if (wpagui->ctrlRequest(cmd, reply, &reply_len) >= 0 && reply_len >= 2 && - reply[0] == '"') { - reply[reply_len] = '\0'; - pos = strchr(reply + 1, '"'); - if (pos) - *pos = '\0'; - identityEdit->setText(reply + 1); - } - - snprintf(cmd, sizeof(cmd), "GET_NETWORK %d password", network_id); - reply_len = sizeof(reply) - 1; - res = wpagui->ctrlRequest(cmd, reply, &reply_len); - if (res >= 0 && reply_len >= 2 && - reply[0] == '"') { - reply[reply_len] = '\0'; - pos = strchr(reply + 1, '"'); - if (pos) - *pos = '\0'; - passwordEdit->setText(reply + 1); - } else if (res >= 0 && key_value_isset(reply, reply_len)) { - passwordEdit->setText(WPA_GUI_KEY_DATA); - } - - snprintf(cmd, sizeof(cmd), "GET_NETWORK %d ca_cert", network_id); - reply_len = sizeof(reply) - 1; - if (wpagui->ctrlRequest(cmd, reply, &reply_len) >= 0 && reply_len >= 2 && - reply[0] == '"') { - reply[reply_len] = '\0'; - pos = strchr(reply + 1, '"'); - if (pos) - *pos = '\0'; - cacertEdit->setText(reply + 1); - } - - snprintf(cmd, sizeof(cmd), "GET_NETWORK %d eap", network_id); - reply_len = sizeof(reply) - 1; - if (wpagui->ctrlRequest(cmd, reply, &reply_len) >= 0 && reply_len >= 1) { - reply[reply_len] = '\0'; - for (i = 0; i < eapSelect->count(); i++) { - if (eapSelect->text(i).compare(reply) == 0) { - eapSelect->setCurrentItem(i); - break; - } - } - } - - for (i = 0; i < 4; i++) { - QLineEdit *wepEdit; - switch (i) { - default: - case 0: - wepEdit = wep0Edit; - break; - case 1: - wepEdit = wep1Edit; - break; - case 2: - wepEdit = wep2Edit; - break; - case 3: - wepEdit = wep3Edit; - break; - } - snprintf(cmd, sizeof(cmd), "GET_NETWORK %d wep_key%d", network_id, i); - reply_len = sizeof(reply) - 1; - res = wpagui->ctrlRequest(cmd, reply, &reply_len); - if (res >= 0 && reply_len >= 2 && reply[0] == '"') { - reply[reply_len] = '\0'; - pos = strchr(reply + 1, '"'); - if (pos) - *pos = '\0'; - if (auth == AUTH_NONE || auth == AUTH_IEEE8021X) - encr = 1; - - wepEdit->setText(reply + 1); - } else if (res >= 0 && key_value_isset(reply, reply_len)) { - if (auth == AUTH_NONE || auth == AUTH_IEEE8021X) - encr = 1; - wepEdit->setText(WPA_GUI_KEY_DATA); - } - } - - snprintf(cmd, sizeof(cmd), "GET_NETWORK %d wep_tx_keyidx", network_id); - reply_len = sizeof(reply) - 1; - if (wpagui->ctrlRequest(cmd, reply, &reply_len) >= 0 && reply_len >= 1) { - reply[reply_len] = '\0'; - switch (atoi(reply)) { - case 0: - wep0Radio->setChecked(true); - break; - case 1: - wep1Radio->setChecked(true); - break; - case 2: - wep2Radio->setChecked(true); - break; - case 3: - wep3Radio->setChecked(true); - break; - } - } - - authSelect->setCurrentItem(auth); - authChanged(auth); - encrSelect->setCurrentItem(encr); - if (auth == AUTH_NONE || auth == AUTH_IEEE8021X) - wepEnabled(encr == 1); - - removeButton->setEnabled(true); - addButton->setText("Save"); -} - - -void NetworkConfig::removeNetwork() -{ - char reply[10], cmd[256]; - size_t reply_len; - - if (QMessageBox::information(this, "wpa_gui", - "This will permanently remove the network\n" - "from the configuration. Do you really want\n" - "to remove this network?", "Yes", "No") != 0) - return; - - snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %d", edit_network_id); - reply_len = sizeof(reply); - wpagui->ctrlRequest(cmd, reply, &reply_len); - if (strncmp(reply, "OK", 2) != 0) { - QMessageBox::warning(this, "wpa_gui", - "Failed to remove network from wpa_supplicant\n" - "configuration."); - } else { - wpagui->triggerUpdate(); - wpagui->ctrlRequest("SAVE_CONFIG", reply, &reply_len); - } - - close(); -} - - -void NetworkConfig::newNetwork() -{ - new_network = true; - getEapCapa(); -} - - -void NetworkConfig::getEapCapa() -{ - char reply[256]; - size_t reply_len; - - if (wpagui == NULL) - return; - - reply_len = sizeof(reply) - 1; - if (wpagui->ctrlRequest("GET_CAPABILITY eap", reply, &reply_len) < 0) - return; - reply[reply_len] = '\0'; - - QString res(reply); - QStringList types = QStringList::split(QChar(' '), res); - eapSelect->insertStringList(types); -} diff --git a/contrib/wpa_supplicant/wpa_gui/scanresults.ui b/contrib/wpa_supplicant/wpa_gui/scanresults.ui deleted file mode 100644 index 66c8b4b76f32..000000000000 --- a/contrib/wpa_supplicant/wpa_gui/scanresults.ui +++ /dev/null @@ -1,179 +0,0 @@ -<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> -<class>ScanResults</class> -<widget class="QDialog"> - <property name="name"> - <cstring>ScanResults</cstring> - </property> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>452</width> - <height>225</height> - </rect> - </property> - <property name="caption"> - <string>Scan results</string> - </property> - <vbox> - <property name="name"> - <cstring>unnamed</cstring> - </property> - <widget class="QListView"> - <column> - <property name="text"> - <string>SSID</string> - </property> - <property name="clickable"> - <bool>true</bool> - </property> - <property name="resizable"> - <bool>true</bool> - </property> - </column> - <column> - <property name="text"> - <string>BSSID</string> - </property> - <property name="clickable"> - <bool>true</bool> - </property> - <property name="resizable"> - <bool>true</bool> - </property> - </column> - <column> - <property name="text"> - <string>frequency</string> - </property> - <property name="clickable"> - <bool>true</bool> - </property> - <property name="resizable"> - <bool>true</bool> - </property> - </column> - <column> - <property name="text"> - <string>signal</string> - </property> - <property name="clickable"> - <bool>true</bool> - </property> - <property name="resizable"> - <bool>true</bool> - </property> - </column> - <column> - <property name="text"> - <string>flags</string> - </property> - <property name="clickable"> - <bool>true</bool> - </property> - <property name="resizable"> - <bool>true</bool> - </property> - </column> - <property name="name"> - <cstring>scanResultsView</cstring> - </property> - <property name="frameShape"> - <enum>StyledPanel</enum> - </property> - <property name="frameShadow"> - <enum>Sunken</enum> - </property> - </widget> - <widget class="QLayoutWidget"> - <property name="name"> - <cstring>layout24</cstring> - </property> - <hbox> - <property name="name"> - <cstring>unnamed</cstring> - </property> - <spacer> - <property name="name"> - <cstring>spacer6</cstring> - </property> - <property name="orientation"> - <enum>Horizontal</enum> - </property> - <property name="sizeType"> - <enum>Expanding</enum> - </property> - <property name="sizeHint"> - <size> - <width>50</width> - <height>20</height> - </size> - </property> - </spacer> - <widget class="QPushButton"> - <property name="name"> - <cstring>scanButton</cstring> - </property> - <property name="text"> - <string>Scan</string> - </property> - </widget> - <widget class="QPushButton"> - <property name="name"> - <cstring>closeButton</cstring> - </property> - <property name="text"> - <string>Close</string> - </property> - </widget> - </hbox> - </widget> - </vbox> -</widget> -<connections> - <connection> - <sender>closeButton</sender> - <signal>clicked()</signal> - <receiver>ScanResults</receiver> - <slot>close()</slot> - </connection> - <connection> - <sender>scanButton</sender> - <signal>clicked()</signal> - <receiver>ScanResults</receiver> - <slot>scanRequest()</slot> - </connection> - <connection> - <sender>scanResultsView</sender> - <signal>doubleClicked(QListViewItem*)</signal> - <receiver>ScanResults</receiver> - <slot>bssSelected(QListViewItem*)</slot> - </connection> -</connections> -<includes> - <include location="local" impldecl="in implementation">wpa_ctrl.h</include> - <include location="local" impldecl="in implementation">wpagui.h</include> - <include location="local" impldecl="in implementation">networkconfig.h</include> - <include location="local" impldecl="in implementation">scanresults.ui.h</include> -</includes> -<forwards> - <forward>class WpaGui;</forward> -</forwards> -<variables> - <variable access="private">WpaGui *wpagui;</variable> - <variable access="private">QTimer *timer;</variable> -</variables> -<slots> - <slot>setWpaGui( WpaGui * _wpagui )</slot> - <slot>updateResults()</slot> - <slot>scanRequest()</slot> - <slot>getResults()</slot> - <slot>bssSelected( QListViewItem * sel )</slot> -</slots> -<functions> - <function access="private" specifier="non virtual">init()</function> - <function access="private" specifier="non virtual">destroy()</function> -</functions> -<pixmapinproject/> -<layoutdefaults spacing="6" margin="11"/> -</UI> diff --git a/contrib/wpa_supplicant/wpa_gui/scanresults.ui.h b/contrib/wpa_supplicant/wpa_gui/scanresults.ui.h deleted file mode 100644 index 530d2e6a495c..000000000000 --- a/contrib/wpa_supplicant/wpa_gui/scanresults.ui.h +++ /dev/null @@ -1,101 +0,0 @@ -/**************************************************************************** -** ui.h extension file, included from the uic-generated form implementation. -** -** If you want to add, delete, or rename functions or slots, use -** Qt Designer to update this file, preserving your code. -** -** You should not define a constructor or destructor in this file. -** Instead, write your code in functions called init() and destroy(). -** These will automatically be called by the form's constructor and -** destructor. -*****************************************************************************/ - -void ScanResults::init() -{ - wpagui = NULL; -} - - -void ScanResults::destroy() -{ - delete timer; -} - - -void ScanResults::setWpaGui(WpaGui *_wpagui) -{ - wpagui = _wpagui; - updateResults(); - - timer = new QTimer(this); - connect(timer, SIGNAL(timeout()), SLOT(getResults())); - timer->start(10000, FALSE); -} - - -void ScanResults::updateResults() -{ - char reply[8192]; - size_t reply_len; - - if (wpagui == NULL) - return; - - reply_len = sizeof(reply) - 1; - if (wpagui->ctrlRequest("SCAN_RESULTS", reply, &reply_len) < 0) - return; - reply[reply_len] = '\0'; - - scanResultsView->clear(); - - QString res(reply); - QStringList lines = QStringList::split(QChar('\n'), res); - bool first = true; - for (QStringList::Iterator it = lines.begin(); it != lines.end(); it++) { - if (first) { - first = false; - continue; - } - - QStringList cols = QStringList::split(QChar('\t'), *it, true); - QString ssid, bssid, freq, signal, flags; - bssid = cols.count() > 0 ? cols[0] : ""; - freq = cols.count() > 1 ? cols[1] : ""; - signal = cols.count() > 2 ? cols[2] : ""; - flags = cols.count() > 3 ? cols[3] : ""; - ssid = cols.count() > 4 ? cols[4] : ""; - new Q3ListViewItem(scanResultsView, ssid, bssid, freq, signal, flags); - } -} - - -void ScanResults::scanRequest() -{ - char reply[10]; - size_t reply_len = sizeof(reply); - - if (wpagui == NULL) - return; - - wpagui->ctrlRequest("SCAN", reply, &reply_len); -} - - -void ScanResults::getResults() -{ - updateResults(); -} - - - - -void ScanResults::bssSelected( Q3ListViewItem * sel ) -{ - NetworkConfig *nc = new NetworkConfig(); - if (nc == NULL) - return; - nc->setWpaGui(wpagui); - nc->paramsFromScanResults(sel); - nc->show(); - nc->exec(); -} diff --git a/contrib/wpa_supplicant/wpa_gui/setup-mingw-cross-compiling b/contrib/wpa_supplicant/wpa_gui/setup-mingw-cross-compiling deleted file mode 100755 index 07e4a8fb6b98..000000000000 --- a/contrib/wpa_supplicant/wpa_gui/setup-mingw-cross-compiling +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -# qmake seems to be forcing include and lib paths from the original build -# and I have no idea how to change these. For now, just override the -# directories in the Makefile.Release file after qmake run. - -qmake -spec /q/jm/qt4-win/4.3.3/mkspecs/win32-g++ wpa_gui.pro -o Makefile -cat Makefile.Release | - sed s%/usr/lib/qt4%/q/jm/qt4-win/4.3.3/lib%g | - sed s%/usr/include/qt4%/q/jm/qt4-win/4.3.3/include%g > tmp.Makefile.Release && -mv -f tmp.Makefile.Release Makefile.Release diff --git a/contrib/wpa_supplicant/wpa_gui/userdatarequest.ui b/contrib/wpa_supplicant/wpa_gui/userdatarequest.ui deleted file mode 100644 index c3d545fa620a..000000000000 --- a/contrib/wpa_supplicant/wpa_gui/userdatarequest.ui +++ /dev/null @@ -1,163 +0,0 @@ -<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> -<class>UserDataRequest</class> -<widget class="QDialog"> - <property name="name"> - <cstring>UserDataRequest</cstring> - </property> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>216</width> - <height>103</height> - </rect> - </property> - <property name="caption"> - <string>Authentication credentials required</string> - </property> - <property name="sizeGripEnabled"> - <bool>true</bool> - </property> - <vbox> - <property name="name"> - <cstring>unnamed</cstring> - </property> - <widget class="QLabel"> - <property name="name"> - <cstring>queryInfo</cstring> - </property> - <property name="text"> - <string></string> - </property> - </widget> - <widget class="QLayoutWidget"> - <property name="name"> - <cstring>layout28</cstring> - </property> - <hbox> - <property name="name"> - <cstring>unnamed</cstring> - </property> - <widget class="QLabel"> - <property name="name"> - <cstring>queryField</cstring> - </property> - <property name="text"> - <string></string> - </property> - </widget> - <widget class="QLineEdit"> - <property name="name"> - <cstring>queryEdit</cstring> - </property> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="echoMode"> - <enum>Password</enum> - </property> - </widget> - </hbox> - </widget> - <widget class="QLayoutWidget"> - <property name="name"> - <cstring>layout27</cstring> - </property> - <hbox> - <property name="name"> - <cstring>unnamed</cstring> - </property> - <spacer> - <property name="name"> - <cstring>spacer4</cstring> - </property> - <property name="orientation"> - <enum>Horizontal</enum> - </property> - <property name="sizeType"> - <enum>Expanding</enum> - </property> - <property name="sizeHint"> - <size> - <width>20</width> - <height>20</height> - </size> - </property> - </spacer> - <widget class="QPushButton"> - <property name="name"> - <cstring>buttonOk</cstring> - </property> - <property name="text"> - <string>&OK</string> - </property> - <property name="accel"> - <string></string> - </property> - <property name="autoDefault"> - <bool>true</bool> - </property> - <property name="default"> - <bool>true</bool> - </property> - </widget> - <widget class="QPushButton"> - <property name="name"> - <cstring>buttonCancel</cstring> - </property> - <property name="text"> - <string>&Cancel</string> - </property> - <property name="accel"> - <string></string> - </property> - <property name="autoDefault"> - <bool>true</bool> - </property> - </widget> - </hbox> - </widget> - </vbox> -</widget> -<connections> - <connection> - <sender>buttonOk</sender> - <signal>clicked()</signal> - <receiver>UserDataRequest</receiver> - <slot>sendReply()</slot> - </connection> - <connection> - <sender>buttonCancel</sender> - <signal>clicked()</signal> - <receiver>UserDataRequest</receiver> - <slot>reject()</slot> - </connection> - <connection> - <sender>queryEdit</sender> - <signal>returnPressed()</signal> - <receiver>UserDataRequest</receiver> - <slot>sendReply()</slot> - </connection> -</connections> -<includes> - <include location="local" impldecl="in implementation">wpa_ctrl.h</include> - <include location="local" impldecl="in implementation">wpagui.h</include> - <include location="local" impldecl="in implementation">userdatarequest.ui.h</include> -</includes> -<forwards> - <forward>class WpaGui;</forward> -</forwards> -<variables> - <variable access="private">WpaGui *wpagui;</variable> - <variable access="private">int networkid;</variable> - <variable access="private">QString field;</variable> -</variables> -<slots> - <slot>sendReply()</slot> -</slots> -<functions> - <function specifier="non virtual" returnType="int">setParams( WpaGui * _wpagui, const char * reqMsg )</function> -</functions> -<pixmapinproject/> -<layoutdefaults spacing="6" margin="11"/> -</UI> diff --git a/contrib/wpa_supplicant/wpa_gui/userdatarequest.ui.h b/contrib/wpa_supplicant/wpa_gui/userdatarequest.ui.h deleted file mode 100644 index 66d4478d23e2..000000000000 --- a/contrib/wpa_supplicant/wpa_gui/userdatarequest.ui.h +++ /dev/null @@ -1,72 +0,0 @@ -/**************************************************************************** -** ui.h extension file, included from the uic-generated form implementation. -** -** If you want to add, delete, or rename functions or slots, use -** Qt Designer to update this file, preserving your code. -** -** You should not define a constructor or destructor in this file. -** Instead, write your code in functions called init() and destroy(). -** These will automatically be called by the form's constructor and -** destructor. -*****************************************************************************/ - -#include <stdlib.h> - -int UserDataRequest::setParams(WpaGui *_wpagui, const char *reqMsg) -{ - char *tmp, *pos, *pos2; - wpagui = _wpagui; - tmp = strdup(reqMsg); - if (tmp == NULL) - return -1; - pos = strchr(tmp, '-'); - if (pos == NULL) { - free(tmp); - return -1; - } - *pos++ = '\0'; - field = tmp; - pos2 = strchr(pos, ':'); - if (pos2 == NULL) { - free(tmp); - return -1; - } - *pos2++ = '\0'; - - networkid = atoi(pos); - queryInfo->setText(pos2); - if (strcmp(tmp, "PASSWORD") == 0) { - queryField->setText("Password: "); - queryEdit->setEchoMode(QLineEdit::Password); - } else if (strcmp(tmp, "NEW_PASSWORD") == 0) { - queryField->setText("New password: "); - queryEdit->setEchoMode(QLineEdit::Password); - } else if (strcmp(tmp, "IDENTITY") == 0) - queryField->setText("Identity: "); - else if (strcmp(tmp, "PASSPHRASE") == 0) { - queryField->setText("Private key passphrase: "); - queryEdit->setEchoMode(QLineEdit::Password); - } else - queryField->setText(field + ":"); - free(tmp); - - return 0; -} - - -void UserDataRequest::sendReply() -{ - char reply[10]; - size_t reply_len = sizeof(reply); - - if (wpagui == NULL) { - reject(); - return; - } - - QString cmd = QString(WPA_CTRL_RSP) + field + '-' + - QString::number(networkid) + ':' + - queryEdit->text(); - wpagui->ctrlRequest(cmd.ascii(), reply, &reply_len); - accept(); -} diff --git a/contrib/wpa_supplicant/wpa_gui/wpa_gui.pro b/contrib/wpa_supplicant/wpa_gui/wpa_gui.pro deleted file mode 100644 index 07829ba30334..000000000000 --- a/contrib/wpa_supplicant/wpa_gui/wpa_gui.pro +++ /dev/null @@ -1,47 +0,0 @@ -TEMPLATE = app -LANGUAGE = C++ - -CONFIG += qt warn_on release - -DEFINES += CONFIG_CTRL_IFACE - -win32 { - LIBS += -lws2_32 -static - DEFINES += CONFIG_NATIVE_WINDOWS CONFIG_CTRL_IFACE_NAMED_PIPE -} else:win32-g++ { - # cross compilation to win32 - LIBS += -lws2_32 -static - DEFINES += CONFIG_NATIVE_WINDOWS CONFIG_CTRL_IFACE_NAMED_PIPE -} else { - DEFINES += CONFIG_CTRL_IFACE_UNIX -} - -INCLUDEPATH += . .. ../../hostapd - -HEADERS += wpamsg.h - -SOURCES += main.cpp \ - ../wpa_ctrl.c - -FORMS = wpagui.ui \ - eventhistory.ui \ - scanresults.ui \ - userdatarequest.ui \ - networkconfig.ui - - -unix { - UI_DIR = .ui - MOC_DIR = .moc - OBJECTS_DIR = .obj -} - -qtver = $$[QT_VERSION] -isEmpty( qtver ) { - message(Compiling for Qt 3.x) - DEFINES += Q3ListViewItem=QListViewItem -} else { - message(Compiling for Qt $$qtver) - QT += qt3support - CONFIG += uic3 -} diff --git a/contrib/wpa_supplicant/wpa_gui/wpagui.ui b/contrib/wpa_supplicant/wpa_gui/wpagui.ui deleted file mode 100644 index 01666a363479..000000000000 --- a/contrib/wpa_supplicant/wpa_gui/wpagui.ui +++ /dev/null @@ -1,471 +0,0 @@ -<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> -<class>WpaGui</class> -<widget class="QMainWindow"> - <property name="name"> - <cstring>WpaGui</cstring> - </property> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>279</width> - <height>308</height> - </rect> - </property> - <property name="caption"> - <string>wpa_gui</string> - </property> - <grid> - <property name="name"> - <cstring>unnamed</cstring> - </property> - <widget class="QLabel" row="0" column="0" rowspan="1" colspan="2"> - <property name="name"> - <cstring>textLabel16</cstring> - </property> - <property name="text"> - <string>Adapter:</string> - </property> - </widget> - <widget class="QComboBox" row="0" column="2" rowspan="1" colspan="2"> - <property name="name"> - <cstring>adapterSelect</cstring> - </property> - </widget> - <widget class="QLabel" row="1" column="0" rowspan="1" colspan="2"> - <property name="name"> - <cstring>textLabel8</cstring> - </property> - <property name="text"> - <string>Network:</string> - </property> - </widget> - <widget class="QComboBox" row="1" column="2" rowspan="1" colspan="2"> - <property name="name"> - <cstring>networkSelect</cstring> - </property> - </widget> - <widget class="QFrame" row="2" column="0" rowspan="1" colspan="4"> - <property name="name"> - <cstring>frame3</cstring> - </property> - <property name="frameShape"> - <enum>StyledPanel</enum> - </property> - <property name="frameShadow"> - <enum>Raised</enum> - </property> - <grid> - <property name="name"> - <cstring>unnamed</cstring> - </property> - <widget class="QLabel" row="0" column="0"> - <property name="name"> - <cstring>textLabel1</cstring> - </property> - <property name="text"> - <string>Status:</string> - </property> - </widget> - <widget class="QLabel" row="1" column="0"> - <property name="name"> - <cstring>textLabel2</cstring> - </property> - <property name="text"> - <string>Last message:</string> - </property> - </widget> - <widget class="QLabel" row="2" column="0"> - <property name="name"> - <cstring>textLabel3</cstring> - </property> - <property name="text"> - <string>Authentication:</string> - </property> - </widget> - <widget class="QLabel" row="3" column="0"> - <property name="name"> - <cstring>textLabel4</cstring> - </property> - <property name="text"> - <string>Encryption:</string> - </property> - </widget> - <widget class="QLabel" row="4" column="0"> - <property name="name"> - <cstring>textLabel5</cstring> - </property> - <property name="text"> - <string>SSID:</string> - </property> - </widget> - <widget class="QLabel" row="5" column="0"> - <property name="name"> - <cstring>textLabel6</cstring> - </property> - <property name="text"> - <string>BSSID:</string> - </property> - </widget> - <widget class="QLabel" row="6" column="0"> - <property name="name"> - <cstring>textLabel7</cstring> - </property> - <property name="text"> - <string>IP address:</string> - </property> - </widget> - <widget class="QLabel" row="0" column="1"> - <property name="name"> - <cstring>textStatus</cstring> - </property> - <property name="text"> - <string></string> - </property> - </widget> - <widget class="QLabel" row="1" column="1" rowspan="1" colspan="3"> - <property name="name"> - <cstring>textLastMessage</cstring> - </property> - <property name="text"> - <string></string> - </property> - </widget> - <widget class="QLabel" row="2" column="1"> - <property name="name"> - <cstring>textAuthentication</cstring> - </property> - <property name="text"> - <string></string> - </property> - </widget> - <widget class="QLabel" row="3" column="1"> - <property name="name"> - <cstring>textEncryption</cstring> - </property> - <property name="text"> - <string></string> - </property> - </widget> - <widget class="QLabel" row="4" column="1"> - <property name="name"> - <cstring>textSsid</cstring> - </property> - <property name="text"> - <string></string> - </property> - </widget> - <widget class="QLabel" row="5" column="1"> - <property name="name"> - <cstring>textBssid</cstring> - </property> - <property name="text"> - <string></string> - </property> - </widget> - <widget class="QLabel" row="6" column="1"> - <property name="name"> - <cstring>textIpAddress</cstring> - </property> - <property name="text"> - <string></string> - </property> - </widget> - </grid> - </widget> - <spacer row="3" column="0"> - <property name="name"> - <cstring>spacer7</cstring> - </property> - <property name="orientation"> - <enum>Horizontal</enum> - </property> - <property name="sizeType"> - <enum>Expanding</enum> - </property> - <property name="sizeHint"> - <size> - <width>16</width> - <height>16</height> - </size> - </property> - </spacer> - <widget class="QPushButton" row="3" column="1"> - <property name="name"> - <cstring>connectButton</cstring> - </property> - <property name="text"> - <string>Connect</string> - </property> - </widget> - <widget class="QPushButton" row="3" column="2"> - <property name="name"> - <cstring>disconnectButton</cstring> - </property> - <property name="text"> - <string>Disconnect</string> - </property> - </widget> - <widget class="QPushButton" row="3" column="3"> - <property name="name"> - <cstring>scanButton</cstring> - </property> - <property name="text"> - <string>Scan</string> - </property> - </widget> - </grid> -</widget> -<menubar> - <property name="name"> - <cstring>MenuBar</cstring> - </property> - <item text="&File" name="fileMenu"> - <separator/> - <action name="fileEventHistoryAction"/> - <action name="fileAdd_NetworkAction"/> - <action name="fileEdit_networkAction"/> - <separator/> - <action name="fileExitAction"/> - </item> - <item text="&Help" name="helpMenu"> - <action name="helpContentsAction"/> - <action name="helpIndexAction"/> - <separator/> - <action name="helpAboutAction"/> - </item> -</menubar> -<toolbars> -</toolbars> -<actions> - <action> - <property name="name"> - <cstring>fileExitAction</cstring> - </property> - <property name="text"> - <string>Exit</string> - </property> - <property name="menuText"> - <string>E&xit</string> - </property> - <property name="accel"> - <string>Ctrl+Q</string> - </property> - </action> - <action> - <property name="name"> - <cstring>helpContentsAction</cstring> - </property> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Contents</string> - </property> - <property name="menuText"> - <string>&Contents...</string> - </property> - <property name="accel"> - <string></string> - </property> - </action> - <action> - <property name="name"> - <cstring>helpIndexAction</cstring> - </property> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Index</string> - </property> - <property name="menuText"> - <string>&Index...</string> - </property> - <property name="accel"> - <string></string> - </property> - </action> - <action> - <property name="name"> - <cstring>helpAboutAction</cstring> - </property> - <property name="text"> - <string>About</string> - </property> - <property name="menuText"> - <string>&About</string> - </property> - <property name="accel"> - <string></string> - </property> - </action> - <action> - <property name="name"> - <cstring>fileEventHistoryAction</cstring> - </property> - <property name="text"> - <string>Event History</string> - </property> - <property name="menuText"> - <string>Event &History</string> - </property> - </action> - <action> - <property name="name"> - <cstring>fileAdd_NetworkAction</cstring> - </property> - <property name="text"> - <string>Add Network</string> - </property> - <property name="menuText"> - <string>&Add Network</string> - </property> - </action> - <action> - <property name="name"> - <cstring>fileEdit_networkAction</cstring> - </property> - <property name="text"> - <string>Edit Network</string> - </property> - <property name="menuText"> - <string>&Edit Network</string> - </property> - </action> -</actions> -<connections> - <connection> - <sender>helpIndexAction</sender> - <signal>activated()</signal> - <receiver>WpaGui</receiver> - <slot>helpIndex()</slot> - </connection> - <connection> - <sender>helpContentsAction</sender> - <signal>activated()</signal> - <receiver>WpaGui</receiver> - <slot>helpContents()</slot> - </connection> - <connection> - <sender>helpAboutAction</sender> - <signal>activated()</signal> - <receiver>WpaGui</receiver> - <slot>helpAbout()</slot> - </connection> - <connection> - <sender>fileExitAction</sender> - <signal>activated()</signal> - <receiver>WpaGui</receiver> - <slot>close()</slot> - </connection> - <connection> - <sender>disconnectButton</sender> - <signal>clicked()</signal> - <receiver>WpaGui</receiver> - <slot>disconnect()</slot> - </connection> - <connection> - <sender>scanButton</sender> - <signal>clicked()</signal> - <receiver>WpaGui</receiver> - <slot>scan()</slot> - </connection> - <connection> - <sender>connectButton</sender> - <signal>clicked()</signal> - <receiver>WpaGui</receiver> - <slot>connectB()</slot> - </connection> - <connection> - <sender>fileEventHistoryAction</sender> - <signal>activated()</signal> - <receiver>WpaGui</receiver> - <slot>eventHistory()</slot> - </connection> - <connection> - <sender>networkSelect</sender> - <signal>activated(const QString&)</signal> - <receiver>WpaGui</receiver> - <slot>selectNetwork(const QString&)</slot> - </connection> - <connection> - <sender>fileEdit_networkAction</sender> - <signal>activated()</signal> - <receiver>WpaGui</receiver> - <slot>editNetwork()</slot> - </connection> - <connection> - <sender>fileAdd_NetworkAction</sender> - <signal>activated()</signal> - <receiver>WpaGui</receiver> - <slot>addNetwork()</slot> - </connection> - <connection> - <sender>adapterSelect</sender> - <signal>activated(const QString&)</signal> - <receiver>WpaGui</receiver> - <slot>selectAdapter(const QString&)</slot> - </connection> -</connections> -<includes> - <include location="global" impldecl="in declaration">qtimer.h</include> - <include location="global" impldecl="in declaration">qsocketnotifier.h</include> - <include location="local" impldecl="in declaration">wpamsg.h</include> - <include location="local" impldecl="in declaration">eventhistory.h</include> - <include location="local" impldecl="in declaration">scanresults.h</include> - <include location="local" impldecl="in implementation">wpa_ctrl.h</include> - <include location="global" impldecl="in implementation">dirent.h</include> - <include location="global" impldecl="in implementation">qmessagebox.h</include> - <include location="global" impldecl="in implementation">qapplication.h</include> - <include location="local" impldecl="in implementation">userdatarequest.h</include> - <include location="local" impldecl="in implementation">networkconfig.h</include> - <include location="local" impldecl="in implementation">wpagui.ui.h</include> -</includes> -<forwards> - <forward>class UserDataRequest;</forward> -</forwards> -<variables> - <variable access="private">ScanResults *scanres;</variable> - <variable access="private">bool networkMayHaveChanged;</variable> - <variable access="private">char *ctrl_iface;</variable> - <variable access="private">EventHistory *eh;</variable> - <variable access="private">struct wpa_ctrl *ctrl_conn;</variable> - <variable access="private">QSocketNotifier *msgNotifier;</variable> - <variable access="private">QTimer *timer;</variable> - <variable access="private">int pingsToStatusUpdate;</variable> - <variable access="private">WpaMsgList msgs;</variable> - <variable access="private">char *ctrl_iface_dir;</variable> - <variable access="private">struct wpa_ctrl *monitor_conn;</variable> - <variable access="private">UserDataRequest *udr;</variable> -</variables> -<slots> - <slot>parse_argv()</slot> - <slot>updateStatus()</slot> - <slot>updateNetworks()</slot> - <slot>helpIndex()</slot> - <slot>helpContents()</slot> - <slot>helpAbout()</slot> - <slot>disconnect()</slot> - <slot>scan()</slot> - <slot>eventHistory()</slot> - <slot>ping()</slot> - <slot>processMsg( char * msg )</slot> - <slot>processCtrlReq( const char * req )</slot> - <slot>receiveMsgs()</slot> - <slot>connectB()</slot> - <slot>selectNetwork( const QString & sel )</slot> - <slot>editNetwork()</slot> - <slot>addNetwork()</slot> - <slot>selectAdapter( const QString & sel )</slot> -</slots> -<functions> - <function access="private" specifier="non virtual">init()</function> - <function access="private" specifier="non virtual">destroy()</function> - <function access="private" specifier="non virtual" returnType="int">openCtrlConnection( const char * ifname )</function> - <function returnType="int">ctrlRequest( const char * cmd, char * buf, size_t * buflen )</function> - <function>triggerUpdate()</function> -</functions> -<pixmapinproject/> -<layoutdefaults spacing="6" margin="11"/> -</UI> diff --git a/contrib/wpa_supplicant/wpa_gui/wpagui.ui.h b/contrib/wpa_supplicant/wpa_gui/wpagui.ui.h deleted file mode 100644 index 3f86c169a73f..000000000000 --- a/contrib/wpa_supplicant/wpa_gui/wpagui.ui.h +++ /dev/null @@ -1,732 +0,0 @@ -/**************************************************************************** -** ui.h extension file, included from the uic-generated form implementation. -** -** If you want to add, delete, or rename functions or slots, use -** Qt Designer to update this file, preserving your code. -** -** You should not define a constructor or destructor in this file. -** Instead, write your code in functions called init() and destroy(). -** These will automatically be called by the form's constructor and -** destructor. -*****************************************************************************/ - - -#ifdef __MINGW32__ -/* Need to get getopt() */ -#include <unistd.h> -#endif - -#include <stdlib.h> - -void WpaGui::init() -{ - eh = NULL; - scanres = NULL; - udr = NULL; - ctrl_iface = NULL; - ctrl_conn = NULL; - monitor_conn = NULL; - msgNotifier = NULL; - ctrl_iface_dir = strdup("/var/run/wpa_supplicant"); - - parse_argv(); - - textStatus->setText("connecting to wpa_supplicant"); - timer = new QTimer(this); - connect(timer, SIGNAL(timeout()), SLOT(ping())); - timer->start(1000, FALSE); - - if (openCtrlConnection(ctrl_iface) < 0) { - printf("Failed to open control connection to wpa_supplicant.\n"); - } - - updateStatus(); - networkMayHaveChanged = true; - updateNetworks(); -} - - -void WpaGui::destroy() -{ - delete msgNotifier; - - if (monitor_conn) { - wpa_ctrl_detach(monitor_conn); - wpa_ctrl_close(monitor_conn); - monitor_conn = NULL; - } - if (ctrl_conn) { - wpa_ctrl_close(ctrl_conn); - ctrl_conn = NULL; - } - - if (eh) { - eh->close(); - delete eh; - eh = NULL; - } - - if (scanres) { - scanres->close(); - delete scanres; - scanres = NULL; - } - - if (udr) { - udr->close(); - delete udr; - udr = NULL; - } - - free(ctrl_iface); - ctrl_iface = NULL; - - free(ctrl_iface_dir); - ctrl_iface_dir = NULL; -} - - -void WpaGui::parse_argv() -{ - int c; - for (;;) { - c = getopt(qApp->argc(), qApp->argv(), "i:p:"); - if (c < 0) - break; - switch (c) { - case 'i': - free(ctrl_iface); - ctrl_iface = strdup(optarg); - break; - case 'p': - free(ctrl_iface_dir); - ctrl_iface_dir = strdup(optarg); - break; - } - } -} - - -int WpaGui::openCtrlConnection(const char *ifname) -{ - char *cfile; - int flen; - char buf[2048], *pos, *pos2; - size_t len; - - if (ifname) { - if (ifname != ctrl_iface) { - free(ctrl_iface); - ctrl_iface = strdup(ifname); - } - } else { -#ifdef CONFIG_CTRL_IFACE_UDP - free(ctrl_iface); - ctrl_iface = strdup("udp"); -#endif /* CONFIG_CTRL_IFACE_UDP */ -#ifdef CONFIG_CTRL_IFACE_UNIX - struct dirent *dent; - DIR *dir = opendir(ctrl_iface_dir); - free(ctrl_iface); - ctrl_iface = NULL; - if (dir) { - 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; - printf("Selected interface '%s'\n", dent->d_name); - ctrl_iface = strdup(dent->d_name); - break; - } - closedir(dir); - } -#endif /* CONFIG_CTRL_IFACE_UNIX */ -#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE - struct wpa_ctrl *ctrl; - int ret; - - free(ctrl_iface); - ctrl_iface = NULL; - - ctrl = wpa_ctrl_open(NULL); - if (ctrl) { - len = sizeof(buf) - 1; - ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL); - if (ret >= 0) { - buf[len] = '\0'; - pos = strchr(buf, '\n'); - if (pos) - *pos = '\0'; - ctrl_iface = strdup(buf); - } - wpa_ctrl_close(ctrl); - } -#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ - } - - if (ctrl_iface == NULL) - return -1; - -#ifdef CONFIG_CTRL_IFACE_UNIX - flen = strlen(ctrl_iface_dir) + strlen(ctrl_iface) + 2; - cfile = (char *) malloc(flen); - if (cfile == NULL) - return -1; - snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ctrl_iface); -#else /* CONFIG_CTRL_IFACE_UNIX */ - flen = strlen(ctrl_iface) + 1; - cfile = (char *) malloc(flen); - if (cfile == NULL) - return -1; - snprintf(cfile, flen, "%s", ctrl_iface); -#endif /* CONFIG_CTRL_IFACE_UNIX */ - - if (ctrl_conn) { - wpa_ctrl_close(ctrl_conn); - ctrl_conn = NULL; - } - - if (monitor_conn) { - delete msgNotifier; - msgNotifier = NULL; - wpa_ctrl_detach(monitor_conn); - wpa_ctrl_close(monitor_conn); - monitor_conn = NULL; - } - - printf("Trying to connect to '%s'\n", cfile); - ctrl_conn = wpa_ctrl_open(cfile); - if (ctrl_conn == NULL) { - free(cfile); - return -1; - } - monitor_conn = wpa_ctrl_open(cfile); - free(cfile); - if (monitor_conn == NULL) { - wpa_ctrl_close(ctrl_conn); - return -1; - } - if (wpa_ctrl_attach(monitor_conn)) { - printf("Failed to attach to wpa_supplicant\n"); - wpa_ctrl_close(monitor_conn); - monitor_conn = NULL; - wpa_ctrl_close(ctrl_conn); - ctrl_conn = NULL; - return -1; - } - -#if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP) - msgNotifier = new QSocketNotifier(wpa_ctrl_get_fd(monitor_conn), - QSocketNotifier::Read, this); - connect(msgNotifier, SIGNAL(activated(int)), SLOT(receiveMsgs())); -#endif - - adapterSelect->clear(); - adapterSelect->insertItem(ctrl_iface); - adapterSelect->setCurrentItem(0); - - len = sizeof(buf) - 1; - if (wpa_ctrl_request(ctrl_conn, "INTERFACES", 10, buf, &len, NULL) >= 0) { - buf[len] = '\0'; - pos = buf; - while (*pos) { - pos2 = strchr(pos, '\n'); - if (pos2) - *pos2 = '\0'; - if (strcmp(pos, ctrl_iface) != 0) - adapterSelect->insertItem(pos); - if (pos2) - pos = pos2 + 1; - else - break; - } - } - - return 0; -} - - -static void wpa_gui_msg_cb(char *msg, size_t) -{ - /* This should not happen anymore since two control connections are used. */ - printf("missed message: %s\n", msg); -} - - -int WpaGui::ctrlRequest(const char *cmd, char *buf, size_t *buflen) -{ - int ret; - - if (ctrl_conn == NULL) - return -3; - ret = wpa_ctrl_request(ctrl_conn, cmd, strlen(cmd), buf, buflen, - wpa_gui_msg_cb); - if (ret == -2) { - printf("'%s' command timed out.\n", cmd); - } else if (ret < 0) { - printf("'%s' command failed.\n", cmd); - } - - return ret; -} - - -void WpaGui::updateStatus() -{ - char buf[2048], *start, *end, *pos; - size_t len; - - pingsToStatusUpdate = 10; - - len = sizeof(buf) - 1; - if (ctrl_conn == NULL || ctrlRequest("STATUS", buf, &len) < 0) { - textStatus->setText("Could not get status from wpa_supplicant"); - textAuthentication->clear(); - textEncryption->clear(); - textSsid->clear(); - textBssid->clear(); - textIpAddress->clear(); - return; - } - - buf[len] = '\0'; - - bool auth_updated = false, ssid_updated = false; - bool bssid_updated = false, ipaddr_updated = false; - bool status_updated = false; - char *pairwise_cipher = NULL, *group_cipher = NULL; - - start = buf; - while (*start) { - bool last = false; - end = strchr(start, '\n'); - if (end == NULL) { - last = true; - end = start; - while (end[0] && end[1]) - end++; - } - *end = '\0'; - - pos = strchr(start, '='); - if (pos) { - *pos++ = '\0'; - if (strcmp(start, "bssid") == 0) { - bssid_updated = true; - textBssid->setText(pos); - } else if (strcmp(start, "ssid") == 0) { - ssid_updated = true; - textSsid->setText(pos); - } else if (strcmp(start, "ip_address") == 0) { - ipaddr_updated = true; - textIpAddress->setText(pos); - } else if (strcmp(start, "wpa_state") == 0) { - status_updated = true; - textStatus->setText(pos); - } else if (strcmp(start, "key_mgmt") == 0) { - auth_updated = true; - textAuthentication->setText(pos); - /* TODO: could add EAP status to this */ - } else if (strcmp(start, "pairwise_cipher") == 0) { - pairwise_cipher = pos; - } else if (strcmp(start, "group_cipher") == 0) { - group_cipher = pos; - } - } - - if (last) - break; - start = end + 1; - } - - if (pairwise_cipher || group_cipher) { - QString encr; - if (pairwise_cipher && group_cipher && - strcmp(pairwise_cipher, group_cipher) != 0) { - encr.append(pairwise_cipher); - encr.append(" + "); - encr.append(group_cipher); - } else if (pairwise_cipher) { - encr.append(pairwise_cipher); - } else if (group_cipher) { - encr.append(group_cipher); - encr.append(" [group key only]"); - } else { - encr.append("?"); - } - textEncryption->setText(encr); - } else - textEncryption->clear(); - - if (!status_updated) - textStatus->clear(); - if (!auth_updated) - textAuthentication->clear(); - if (!ssid_updated) - textSsid->clear(); - if (!bssid_updated) - textBssid->clear(); - if (!ipaddr_updated) - textIpAddress->clear(); -} - - -void WpaGui::updateNetworks() -{ - char buf[2048], *start, *end, *id, *ssid, *bssid, *flags; - size_t len; - int first_active = -1; - bool selected = false; - - if (!networkMayHaveChanged) - return; - - networkSelect->clear(); - - if (ctrl_conn == NULL) - return; - - len = sizeof(buf) - 1; - if (ctrlRequest("LIST_NETWORKS", buf, &len) < 0) - return; - - buf[len] = '\0'; - start = strchr(buf, '\n'); - if (start == NULL) - return; - start++; - - while (*start) { - bool last = false; - end = strchr(start, '\n'); - if (end == NULL) { - last = true; - end = start; - while (end[0] && end[1]) - end++; - } - *end = '\0'; - - id = start; - ssid = strchr(id, '\t'); - if (ssid == NULL) - break; - *ssid++ = '\0'; - bssid = strchr(ssid, '\t'); - if (bssid == NULL) - break; - *bssid++ = '\0'; - flags = strchr(bssid, '\t'); - if (flags == NULL) - break; - *flags++ = '\0'; - - QString network(id); - network.append(": "); - network.append(ssid); - networkSelect->insertItem(network); - - if (strstr(flags, "[CURRENT]")) { - networkSelect->setCurrentItem(networkSelect->count() - 1); - selected = true; - } else if (first_active < 0 && strstr(flags, "[DISABLED]") == NULL) - first_active = networkSelect->count() - 1; - - if (last) - break; - start = end + 1; - } - - if (!selected && first_active >= 0) - networkSelect->setCurrentItem(first_active); - - networkMayHaveChanged = false; -} - - -void WpaGui::helpIndex() -{ - printf("helpIndex\n"); -} - - -void WpaGui::helpContents() -{ - printf("helpContents\n"); -} - - -void WpaGui::helpAbout() -{ - QMessageBox::about(this, "wpa_gui for wpa_supplicant", - "Copyright (c) 2003-2008,\n" - "Jouni Malinen <j@w1.fi>\n" - "and contributors.\n" - "\n" - "This program is free software. You can\n" - "distribute it and/or modify it under the terms of\n" - "the GNU General Public License version 2.\n" - "\n" - "Alternatively, this software may be distributed\n" - "under the terms of the BSD license.\n" - "\n" - "This product includes software developed\n" - "by the OpenSSL Project for use in the\n" - "OpenSSL Toolkit (http://www.openssl.org/)\n"); -} - - -void WpaGui::disconnect() -{ - char reply[10]; - size_t reply_len = sizeof(reply); - ctrlRequest("DISCONNECT", reply, &reply_len); -} - - -void WpaGui::scan() -{ - if (scanres) { - scanres->close(); - delete scanres; - } - - scanres = new ScanResults(); - if (scanres == NULL) - return; - scanres->setWpaGui(this); - scanres->show(); - scanres->exec(); -} - - -void WpaGui::eventHistory() -{ - if (eh) { - eh->close(); - delete eh; - } - - eh = new EventHistory(); - if (eh == NULL) - return; - eh->addEvents(msgs); - eh->show(); - eh->exec(); -} - - -void WpaGui::ping() -{ - char buf[10]; - size_t len; - -#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE - /* - * QSocketNotifier cannot be used with Windows named pipes, so use a timer - * to check for received messages for now. This could be optimized be doing - * something specific to named pipes or Windows events, but it is not clear - * what would be the best way of doing that in Qt. - */ - receiveMsgs(); -#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ - - if (scanres && !scanres->isVisible()) { - delete scanres; - scanres = NULL; - } - - if (eh && !eh->isVisible()) { - delete eh; - eh = NULL; - } - - if (udr && !udr->isVisible()) { - delete udr; - udr = NULL; - } - - len = sizeof(buf) - 1; - if (ctrlRequest("PING", buf, &len) < 0) { - printf("PING failed - trying to reconnect\n"); - if (openCtrlConnection(ctrl_iface) >= 0) { - printf("Reconnected successfully\n"); - pingsToStatusUpdate = 0; - } - } - - pingsToStatusUpdate--; - if (pingsToStatusUpdate <= 0) { - updateStatus(); - updateNetworks(); - } -} - - -static int str_match(const char *a, const char *b) -{ - return strncmp(a, b, strlen(b)) == 0; -} - - -void WpaGui::processMsg(char *msg) -{ - char *pos = msg, *pos2; - int priority = 2; - - if (*pos == '<') { - /* skip priority */ - pos++; - priority = atoi(pos); - pos = strchr(pos, '>'); - if (pos) - pos++; - else - pos = msg; - } - - WpaMsg wm(pos, priority); - if (eh) - eh->addEvent(wm); - msgs.append(wm); - while (msgs.count() > 100) - msgs.pop_front(); - - /* Update last message with truncated version of the event */ - if (strncmp(pos, "CTRL-", 5) == 0) { - pos2 = strchr(pos, str_match(pos, WPA_CTRL_REQ) ? ':' : ' '); - if (pos2) - pos2++; - else - pos2 = pos; - } else - pos2 = pos; - QString lastmsg = pos2; - lastmsg.truncate(40); - textLastMessage->setText(lastmsg); - - pingsToStatusUpdate = 0; - networkMayHaveChanged = true; - - if (str_match(pos, WPA_CTRL_REQ)) - processCtrlReq(pos + strlen(WPA_CTRL_REQ)); -} - - -void WpaGui::processCtrlReq(const char *req) -{ - if (udr) { - udr->close(); - delete udr; - } - udr = new UserDataRequest(); - if (udr == NULL) - return; - if (udr->setParams(this, req) < 0) { - delete udr; - udr = NULL; - return; - } - udr->show(); - udr->exec(); -} - - -void WpaGui::receiveMsgs() -{ - char buf[256]; - size_t len; - - while (monitor_conn && wpa_ctrl_pending(monitor_conn) > 0) { - len = sizeof(buf) - 1; - if (wpa_ctrl_recv(monitor_conn, buf, &len) == 0) { - buf[len] = '\0'; - processMsg(buf); - } - } -} - - -void WpaGui::connectB() -{ - char reply[10]; - size_t reply_len = sizeof(reply); - ctrlRequest("REASSOCIATE", reply, &reply_len); -} - - -void WpaGui::selectNetwork( const QString &sel ) -{ - QString cmd(sel); - char reply[10]; - size_t reply_len = sizeof(reply); - - int pos = cmd.find(':'); - if (pos < 0) { - printf("Invalid selectNetwork '%s'\n", cmd.ascii()); - return; - } - cmd.truncate(pos); - cmd.prepend("SELECT_NETWORK "); - ctrlRequest(cmd.ascii(), reply, &reply_len); -} - - -void WpaGui::editNetwork() -{ - QString sel(networkSelect->currentText()); - int pos = sel.find(':'); - if (pos < 0) { - printf("Invalid selectNetwork '%s'\n", sel.ascii()); - return; - } - sel.truncate(pos); - - NetworkConfig *nc = new NetworkConfig(); - if (nc == NULL) - return; - nc->setWpaGui(this); - - nc->paramsFromConfig(sel.toInt()); - nc->show(); - nc->exec(); -} - - -void WpaGui::triggerUpdate() -{ - updateStatus(); - networkMayHaveChanged = true; - updateNetworks(); -} - - -void WpaGui::addNetwork() -{ - NetworkConfig *nc = new NetworkConfig(); - if (nc == NULL) - return; - nc->setWpaGui(this); - nc->newNetwork(); - nc->show(); - nc->exec(); -} - - -void WpaGui::selectAdapter( const QString & sel ) -{ - if (openCtrlConnection(sel.ascii()) < 0) - printf("Failed to open control connection to wpa_supplicant.\n"); - updateStatus(); - updateNetworks(); -} diff --git a/contrib/wpa_supplicant/wpa_gui/wpamsg.h b/contrib/wpa_supplicant/wpa_gui/wpamsg.h deleted file mode 100644 index f3fce06978c7..000000000000 --- a/contrib/wpa_supplicant/wpa_gui/wpamsg.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef WPAMSG_H -#define WPAMSG_H - -class WpaMsg; - -#if QT_VERSION >= 0x040000 -#include <QDateTime> -#include <QLinkedList> -typedef QLinkedList<WpaMsg> WpaMsgList; -#else -#include <qdatetime.h> -typedef QValueList<WpaMsg> WpaMsgList; -#endif - -class WpaMsg { -public: - WpaMsg() {} - WpaMsg(const QString &_msg, int _priority = 2) - : msg(_msg), priority(_priority) - { - timestamp = QDateTime::currentDateTime(); - } - - QString getMsg() const { return msg; } - int getPriority() const { return priority; } - QDateTime getTimestamp() const { return timestamp; } - -private: - QString msg; - int priority; - QDateTime timestamp; -}; - -#endif /* WPAMSG_H */ diff --git a/contrib/wpa_supplicant/wpa_i.h b/contrib/wpa_supplicant/wpa_i.h deleted file mode 100644 index d1cab4bbf945..000000000000 --- a/contrib/wpa_supplicant/wpa_i.h +++ /dev/null @@ -1,221 +0,0 @@ -/* - * wpa_supplicant - Internal WPA state machine definitions - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 - -struct rsn_pmksa_candidate; - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -/** - * 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; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - - -#ifdef CONFIG_PEERKEY -#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; - - struct wpa_ptk stk, tstk; - int stk_set, tstk_set; -}; -#else /* CONFIG_PEERKEY */ -struct wpa_peerkey; -#endif /* CONFIG_PEERKEY */ - - -/** - * 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 rsn_pmksa_candidate *pmksa_candidates; - - struct l2_packet_data *l2_preauth; - struct l2_packet_data *l2_preauth_br; - 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 */ - - struct wpa_ssid *cur_ssid; - - 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; - - 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 */ -}; - - -static inline void wpa_sm_set_state(struct wpa_sm *sm, wpa_states state) -{ - sm->ctx->set_state(sm->ctx->ctx, state); -} - -static inline wpa_states wpa_sm_get_state(struct wpa_sm *sm) -{ - return sm->ctx->get_state(sm->ctx->ctx); -} - -static inline void wpa_sm_deauthenticate(struct wpa_sm *sm, int reason_code) -{ - sm->ctx->deauthenticate(sm->ctx->ctx, reason_code); -} - -static inline void wpa_sm_disassociate(struct wpa_sm *sm, int reason_code) -{ - sm->ctx->disassociate(sm->ctx->ctx, reason_code); -} - -static inline int wpa_sm_set_key(struct wpa_sm *sm, 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) -{ - return sm->ctx->set_key(sm->ctx->ctx, alg, addr, key_idx, set_tx, - seq, seq_len, key, key_len); -} - -static inline struct wpa_ssid * wpa_sm_get_ssid(struct wpa_sm *sm) -{ - return sm->ctx->get_ssid(sm->ctx->ctx); -} - -static inline int wpa_sm_get_bssid(struct wpa_sm *sm, u8 *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) -{ - return sm->ctx->ether_send(sm->ctx->ctx, dest, proto, buf, len); -} - -static inline int wpa_sm_get_beacon_ie(struct wpa_sm *sm) -{ - return sm->ctx->get_beacon_ie(sm->ctx->ctx); -} - -static inline void wpa_sm_cancel_auth_timeout(struct wpa_sm *sm) -{ - 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) -{ - 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) -{ - 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) -{ - 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) -{ - return sm->ctx->mlme_setprotection(sm->ctx->ctx, addr, protect_type, - key_type); -} - -#endif /* WPA_I_H */ diff --git a/contrib/wpa_supplicant/wpa_passphrase.c b/contrib/wpa_supplicant/wpa_passphrase.c deleted file mode 100644 index 96b0c32c2cee..000000000000 --- a/contrib/wpa_supplicant/wpa_passphrase.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * WPA Supplicant - ASCII passphrase to WPA PSK tool - * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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" - - -int main(int argc, char *argv[]) -{ - unsigned char psk[32]; - int i; - char *ssid, *passphrase, buf[64], *pos; - - if (argc < 2) { - printf("usage: wpa_passphrase <ssid> [passphrase]\n" - "\nIf passphrase is left out, it will be read from " - "stdin\n"); - return 1; - } - - ssid = argv[1]; - - if (argc > 2) { - passphrase = argv[2]; - } else { - printf("# reading passphrase from stdin\n"); - if (fgets(buf, sizeof(buf), stdin) == NULL) { - printf("Failed to read passphrase\n"); - return 1; - } - buf[sizeof(buf) - 1] = '\0'; - pos = buf; - while (*pos != '\0') { - if (*pos == '\r' || *pos == '\n') { - *pos = '\0'; - break; - } - pos++; - } - passphrase = buf; - } - - if (os_strlen(passphrase) < 8 || os_strlen(passphrase) > 63) { - printf("Passphrase must be 8..63 characters\n"); - return 1; - } - - pbkdf2_sha1(passphrase, ssid, os_strlen(ssid), 4096, psk, 32); - - printf("network={\n"); - printf("\tssid=\"%s\"\n", ssid); - printf("\t#psk=\"%s\"\n", passphrase); - printf("\tpsk="); - for (i = 0; i < 32; i++) - printf("%02x", psk[i]); - printf("\n"); - printf("}\n"); - - return 0; -} diff --git a/contrib/wpa_supplicant/wpa_supplicant.c b/contrib/wpa_supplicant/wpa_supplicant.c deleted file mode 100644 index a795e4a50550..000000000000 --- a/contrib/wpa_supplicant/wpa_supplicant.c +++ /dev/null @@ -1,2642 +0,0 @@ -/* - * WPA Supplicant - * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 functions for registering and unregistering - * %wpa_supplicant interfaces. In addition, this file contains number of - * functions for managing network connections. - * - * $FreeBSD$ - */ - -#include "includes.h" - -#include "common.h" -#include "eapol_sm.h" -#include "eap.h" -#include "wpa.h" -#include "eloop.h" -#include "wpa_supplicant.h" -#include "config.h" -#include "l2_packet.h" -#include "wpa_supplicant_i.h" -#include "ctrl_iface.h" -#include "ctrl_iface_dbus.h" -#include "pcsc_funcs.h" -#include "version.h" -#include "preauth.h" -#include "pmksa_cache.h" -#include "wpa_ctrl.h" -#include "mlme.h" - -const char *wpa_supplicant_version = -"wpa_supplicant v" VERSION_STR "\n" -"Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi> and contributors"; - -const char *wpa_supplicant_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" -#ifdef EAP_TLS_OPENSSL -"\nThis product includes software developed by the OpenSSL Project\n" -"for use in the OpenSSL Toolkit (http://www.openssl.org/)\n" -#endif /* EAP_TLS_OPENSSL */ -; - -#ifndef CONFIG_NO_STDOUT_DEBUG -/* Long text divided into parts in order to fit in C89 strings size limits. */ -const char *wpa_supplicant_full_license1 = -"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"; -const char *wpa_supplicant_full_license2 = -"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"; -const char *wpa_supplicant_full_license3 = -"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"; -const char *wpa_supplicant_full_license4 = -"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"; -const char *wpa_supplicant_full_license5 = -"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"; -#endif /* CONFIG_NO_STDOUT_DEBUG */ - -extern struct wpa_driver_ops *wpa_supplicant_drivers[]; - -extern int wpa_debug_level; -extern int wpa_debug_show_keys; -extern int wpa_debug_timestamp; - -static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx); - -#if defined(IEEE8021X_EAPOL) || !defined(CONFIG_NO_WPA) -static u8 * wpa_alloc_eapol(const struct wpa_supplicant *wpa_s, u8 type, - const void *data, u16 data_len, - size_t *msg_len, void **data_pos) -{ - struct ieee802_1x_hdr *hdr; - - *msg_len = sizeof(*hdr) + data_len; - hdr = os_malloc(*msg_len); - if (hdr == NULL) - return NULL; - - hdr->version = wpa_s->conf->eapol_version; - hdr->type = type; - hdr->length = host_to_be16(data_len); - - if (data) - os_memcpy(hdr + 1, data, data_len); - else - os_memset(hdr + 1, 0, data_len); - - if (data_pos) - *data_pos = hdr + 1; - - return (u8 *) hdr; -} - - -/** - * wpa_ether_send - Send Ethernet frame - * @wpa_s: Pointer to wpa_supplicant data - * @dest: Destination MAC address - * @proto: Ethertype in host byte order - * @buf: Frame payload starting from IEEE 802.1X header - * @len: Frame payload length - * Returns: >=0 on success, <0 on failure - */ -static int wpa_ether_send(struct wpa_supplicant *wpa_s, const u8 *dest, - u16 proto, const u8 *buf, size_t len) -{ - if (wpa_s->l2) { - return l2_packet_send(wpa_s->l2, dest, proto, buf, len); - } - - return wpa_drv_send_eapol(wpa_s, dest, proto, buf, len); -} -#endif /* IEEE8021X_EAPOL || !CONFIG_NO_WPA */ - - -#ifdef IEEE8021X_EAPOL -/** - * wpa_supplicant_eapol_send - Send IEEE 802.1X EAPOL packet to Authenticator - * @ctx: Pointer to wpa_supplicant data (wpa_s) - * @type: IEEE 802.1X packet type (IEEE802_1X_TYPE_*) - * @buf: EAPOL payload (after IEEE 802.1X header) - * @len: EAPOL payload length - * Returns: >=0 on success, <0 on failure - * - * This function adds Ethernet and IEEE 802.1X header and sends the EAPOL frame - * to the current Authenticator. - */ -static int wpa_supplicant_eapol_send(void *ctx, int type, const u8 *buf, - size_t len) -{ - struct wpa_supplicant *wpa_s = ctx; - u8 *msg, *dst, bssid[ETH_ALEN]; - size_t msglen; - int res; - - /* TODO: could add l2_packet_sendmsg that allows fragments to avoid - * extra copy here */ - - if (wpa_s->key_mgmt == WPA_KEY_MGMT_PSK || - wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) { - /* Current SSID is not using IEEE 802.1X/EAP, so drop possible - * EAPOL frames (mainly, EAPOL-Start) from EAPOL state - * machines. */ - wpa_printf(MSG_DEBUG, "WPA: drop TX EAPOL in non-IEEE 802.1X " - "mode (type=%d len=%lu)", type, - (unsigned long) len); - return -1; - } - - if (pmksa_cache_get_current(wpa_s->wpa) && - type == IEEE802_1X_TYPE_EAPOL_START) { - /* Trying to use PMKSA caching - do not send EAPOL-Start frames - * since they will trigger full EAPOL authentication. */ - wpa_printf(MSG_DEBUG, "RSN: PMKSA caching - do not send " - "EAPOL-Start"); - return -1; - } - - if (os_memcmp(wpa_s->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0) - { - wpa_printf(MSG_DEBUG, "BSSID not set when trying to send an " - "EAPOL frame"); - if (wpa_drv_get_bssid(wpa_s, bssid) == 0 && - os_memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) != - 0) { - dst = bssid; - wpa_printf(MSG_DEBUG, "Using current BSSID " MACSTR - " from the driver as the EAPOL destination", - MAC2STR(dst)); - } else { - dst = wpa_s->last_eapol_src; - wpa_printf(MSG_DEBUG, "Using the source address of the" - " last received EAPOL frame " MACSTR " as " - "the EAPOL destination", - MAC2STR(dst)); - } - } else { - /* BSSID was already set (from (Re)Assoc event, so use it as - * the EAPOL destination. */ - dst = wpa_s->bssid; - } - - msg = wpa_alloc_eapol(wpa_s, type, buf, len, &msglen, NULL); - if (msg == NULL) - return -1; - - wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", msg, msglen); - res = wpa_ether_send(wpa_s, dst, ETH_P_EAPOL, msg, msglen); - os_free(msg); - return res; -} - - -/** - * wpa_eapol_set_wep_key - set WEP key for the driver - * @ctx: Pointer to wpa_supplicant data (wpa_s) - * @unicast: 1 = individual unicast key, 0 = broadcast key - * @keyidx: WEP key index (0..3) - * @key: Pointer to key data - * @keylen: Key length in bytes - * Returns: 0 on success or < 0 on error. - */ -static int wpa_eapol_set_wep_key(void *ctx, int unicast, int keyidx, - const u8 *key, size_t keylen) -{ - struct wpa_supplicant *wpa_s = ctx; - if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { - int cipher = (keylen == 5) ? WPA_CIPHER_WEP40 : - WPA_CIPHER_WEP104; - if (unicast) - wpa_s->pairwise_cipher = cipher; - else - wpa_s->group_cipher = cipher; - } - return wpa_drv_set_key(wpa_s, WPA_ALG_WEP, - unicast ? wpa_s->bssid : - (u8 *) "\xff\xff\xff\xff\xff\xff", - keyidx, unicast, (u8 *) "", 0, key, keylen); -} - - -static void wpa_supplicant_aborted_cached(void *ctx) -{ - struct wpa_supplicant *wpa_s = ctx; - wpa_sm_aborted_cached(wpa_s->wpa); -} - -#endif /* IEEE8021X_EAPOL */ - - -#if defined(IEEE8021X_EAPOL) || !defined(CONFIG_NO_WPA) -static void wpa_supplicant_set_config_blob(void *ctx, - struct wpa_config_blob *blob) -{ - struct wpa_supplicant *wpa_s = ctx; - wpa_config_set_blob(wpa_s->conf, blob); -} - - -static const struct wpa_config_blob * -wpa_supplicant_get_config_blob(void *ctx, const char *name) -{ - struct wpa_supplicant *wpa_s = ctx; - return wpa_config_get_blob(wpa_s->conf, name); -} -#endif /* defined(IEEE8021X_EAPOL) || !defined(CONFIG_NO_WPA) */ - - -/* Configure default/group WEP key for static WEP */ -static int wpa_set_wep_key(void *ctx, int set_tx, int keyidx, const u8 *key, - size_t keylen) -{ - struct wpa_supplicant *wpa_s = ctx; - return wpa_drv_set_key(wpa_s, WPA_ALG_WEP, - (u8 *) "\xff\xff\xff\xff\xff\xff", - keyidx, set_tx, (u8 *) "", 0, key, keylen); -} - - -static int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s, - struct wpa_ssid *ssid) -{ - u8 key[32]; - size_t keylen; - wpa_alg alg; - u8 seq[6] = { 0 }; - - /* IBSS/WPA-None uses only one key (Group) for both receiving and - * sending unicast and multicast packets. */ - - if (ssid->mode != IEEE80211_MODE_IBSS) { - wpa_printf(MSG_INFO, "WPA: Invalid mode %d (not IBSS/ad-hoc) " - "for WPA-None", ssid->mode); - return -1; - } - - if (!ssid->psk_set) { - wpa_printf(MSG_INFO, "WPA: No PSK configured for WPA-None"); - return -1; - } - - switch (wpa_s->group_cipher) { - case WPA_CIPHER_CCMP: - os_memcpy(key, ssid->psk, 16); - keylen = 16; - alg = WPA_ALG_CCMP; - break; - case WPA_CIPHER_TKIP: - /* WPA-None uses the same Michael MIC key for both TX and RX */ - os_memcpy(key, ssid->psk, 16 + 8); - os_memcpy(key + 16 + 8, ssid->psk + 16, 8); - keylen = 32; - alg = WPA_ALG_TKIP; - break; - default: - wpa_printf(MSG_INFO, "WPA: Invalid group cipher %d for " - "WPA-None", wpa_s->group_cipher); - return -1; - } - - /* TODO: should actually remember the previously used seq#, both for TX - * and RX from each STA.. */ - - return wpa_drv_set_key(wpa_s, alg, (u8 *) "\xff\xff\xff\xff\xff\xff", - 0, 1, seq, 6, key, keylen); -} - - -#ifdef IEEE8021X_EAPOL -static void wpa_supplicant_notify_eapol_done(void *ctx) -{ - struct wpa_supplicant *wpa_s = ctx; - wpa_msg(wpa_s, MSG_DEBUG, "WPA: EAPOL processing complete"); - if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X) { - wpa_supplicant_set_state(wpa_s, WPA_4WAY_HANDSHAKE); - } else { - wpa_supplicant_cancel_auth_timeout(wpa_s); - wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); - } -} -#endif /* IEEE8021X_EAPOL */ - - -/** - * wpa_blacklist_get - Get the blacklist entry for a BSSID - * @wpa_s: Pointer to wpa_supplicant data - * @bssid: BSSID - * Returns: Matching blacklist entry for the BSSID or %NULL if not found - */ -struct wpa_blacklist * wpa_blacklist_get(struct wpa_supplicant *wpa_s, - const u8 *bssid) -{ - struct wpa_blacklist *e; - - e = wpa_s->blacklist; - while (e) { - if (os_memcmp(e->bssid, bssid, ETH_ALEN) == 0) - return e; - e = e->next; - } - - return NULL; -} - - -/** - * wpa_blacklist_add - Add an BSSID to the blacklist - * @wpa_s: Pointer to wpa_supplicant data - * @bssid: BSSID to be added to the blacklist - * Returns: 0 on success, -1 on failure - * - * This function adds the specified BSSID to the blacklist or increases the - * blacklist count if the BSSID was already listed. It should be called when - * an association attempt fails either due to the selected BSS rejecting - * association or due to timeout. - * - * This blacklist is used to force %wpa_supplicant to go through all available - * BSSes before retrying to associate with an BSS that rejected or timed out - * association. It does not prevent the listed BSS from being used; it only - * changes the order in which they are tried. - */ -int wpa_blacklist_add(struct wpa_supplicant *wpa_s, const u8 *bssid) -{ - struct wpa_blacklist *e; - - e = wpa_blacklist_get(wpa_s, bssid); - if (e) { - e->count++; - wpa_printf(MSG_DEBUG, "BSSID " MACSTR " blacklist count " - "incremented to %d", - MAC2STR(bssid), e->count); - return 0; - } - - e = os_zalloc(sizeof(*e)); - if (e == NULL) - return -1; - os_memcpy(e->bssid, bssid, ETH_ALEN); - e->count = 1; - e->next = wpa_s->blacklist; - wpa_s->blacklist = e; - wpa_printf(MSG_DEBUG, "Added BSSID " MACSTR " into blacklist", - MAC2STR(bssid)); - - return 0; -} - - -static int wpa_blacklist_del(struct wpa_supplicant *wpa_s, const u8 *bssid) -{ - struct wpa_blacklist *e, *prev = NULL; - - e = wpa_s->blacklist; - while (e) { - if (os_memcmp(e->bssid, bssid, ETH_ALEN) == 0) { - if (prev == NULL) { - wpa_s->blacklist = e->next; - } else { - prev->next = e->next; - } - wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR " from " - "blacklist", MAC2STR(bssid)); - os_free(e); - return 0; - } - prev = e; - e = e->next; - } - return -1; -} - - -/** - * wpa_blacklist_clear - Clear the blacklist of all entries - * @wpa_s: Pointer to wpa_supplicant data - */ -void wpa_blacklist_clear(struct wpa_supplicant *wpa_s) -{ - struct wpa_blacklist *e, *prev; - - e = wpa_s->blacklist; - wpa_s->blacklist = NULL; - while (e) { - prev = e; - e = e->next; - wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR " from " - "blacklist (clear)", MAC2STR(prev->bssid)); - os_free(prev); - } -} - - -/** - * wpa_supplicant_req_scan - Schedule a scan for neighboring access points - * @wpa_s: Pointer to wpa_supplicant data - * @sec: Number of seconds after which to scan - * @usec: Number of microseconds after which to scan - * - * This function is used to schedule a scan for neighboring access points after - * the specified time. - */ -void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec) -{ - /* If there's at least one network that should be specifically scanned - * then don't cancel the scan and reschedule. Some drivers do - * background scanning which generates frequent scan results, and that - * causes the specific SSID scan to get continually pushed back and - * never happen, which causes hidden APs to never get probe-scanned. - */ - if (eloop_is_timeout_registered(wpa_supplicant_scan, wpa_s, NULL) && - wpa_s->conf->ap_scan == 1) { - struct wpa_ssid *ssid = wpa_s->conf->ssid; - - while (ssid) { - if (!ssid->disabled && ssid->scan_ssid) - break; - ssid = ssid->next; - } - if (ssid) { - wpa_msg(wpa_s, MSG_DEBUG, "Not rescheduling scan to " - "ensure that specific SSID scans occur"); - return; - } - } - - wpa_msg(wpa_s, MSG_DEBUG, "Setting scan request: %d sec %d usec", - sec, usec); - eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL); - eloop_register_timeout(sec, usec, wpa_supplicant_scan, wpa_s, NULL); -} - - -/** - * wpa_supplicant_cancel_scan - Cancel a scheduled scan request - * @wpa_s: Pointer to wpa_supplicant data - * - * This function is used to cancel a scan request scheduled with - * wpa_supplicant_req_scan(). - */ -void wpa_supplicant_cancel_scan(struct wpa_supplicant *wpa_s) -{ - wpa_msg(wpa_s, MSG_DEBUG, "Cancelling scan request"); - eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL); -} - - -static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_supplicant *wpa_s = eloop_ctx; - const u8 *bssid = wpa_s->bssid; - if (os_memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0) - bssid = wpa_s->pending_bssid; - wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.", - MAC2STR(bssid)); - wpa_blacklist_add(wpa_s, bssid); - wpa_sm_notify_disassoc(wpa_s->wpa); - wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING); - wpa_s->reassociate = 1; - wpa_supplicant_req_scan(wpa_s, 0, 0); -} - - -/** - * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication - * @wpa_s: Pointer to wpa_supplicant data - * @sec: Number of seconds after which to time out authentication - * @usec: Number of microseconds after which to time out authentication - * - * This function is used to schedule a timeout for the current authentication - * attempt. - */ -void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s, - int sec, int usec) -{ - if (wpa_s->conf && wpa_s->conf->ap_scan == 0 && - wpa_s->driver && os_strcmp(wpa_s->driver->name, "wired") == 0) - return; - - wpa_msg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec " - "%d usec", sec, usec); - eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL); - eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL); -} - - -/** - * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout - * @wpa_s: Pointer to wpa_supplicant data - * - * This function is used to cancel authentication timeout scheduled with - * wpa_supplicant_req_auth_timeout() and it is called when authentication has - * been completed. - */ -void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s) -{ - wpa_msg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout"); - eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL); - wpa_blacklist_del(wpa_s, wpa_s->bssid); -} - - -/** - * wpa_supplicant_initiate_eapol - Configure EAPOL state machine - * @wpa_s: Pointer to wpa_supplicant data - * - * This function is used to configure EAPOL state machine based on the selected - * authentication mode. - */ -void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s) -{ -#ifdef IEEE8021X_EAPOL - struct eapol_config eapol_conf; - struct wpa_ssid *ssid = wpa_s->current_ssid; - - if (wpa_s->key_mgmt == WPA_KEY_MGMT_PSK) { - eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); - eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE); - } - if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE || - wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) - eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized); - else - eapol_sm_notify_portControl(wpa_s->eapol, Auto); - - os_memset(&eapol_conf, 0, sizeof(eapol_conf)); - if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { - eapol_conf.accept_802_1x_keys = 1; - eapol_conf.required_keys = 0; - if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) { - eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST; - } - if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) { - eapol_conf.required_keys |= - EAPOL_REQUIRE_KEY_BROADCAST; - } - - if (wpa_s->conf && wpa_s->driver && - os_strcmp(wpa_s->driver->name, "wired") == 0) { - eapol_conf.required_keys = 0; - } - } - if (wpa_s->conf) - eapol_conf.fast_reauth = wpa_s->conf->fast_reauth; - eapol_conf.workaround = ssid->eap_workaround; - eapol_conf.eap_disabled = wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X && - wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA; - eapol_sm_notify_config(wpa_s->eapol, ssid, &eapol_conf); -#endif /* IEEE8021X_EAPOL */ -} - - -/** - * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode - * @wpa_s: Pointer to wpa_supplicant data - * @ssid: Configuration data for the network - * - * This function is used to configure WPA state machine and related parameters - * to a mode where WPA is not enabled. This is called as part of the - * authentication configuration when the selected network does not use WPA. - */ -void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s, - struct wpa_ssid *ssid) -{ - int i; - - if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) - wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA; - else - wpa_s->key_mgmt = WPA_KEY_MGMT_NONE; - wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0); - wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0); - wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0); - wpa_s->pairwise_cipher = WPA_CIPHER_NONE; - wpa_s->group_cipher = WPA_CIPHER_NONE; - wpa_s->mgmt_group_cipher = 0; - - for (i = 0; i < NUM_WEP_KEYS; i++) { - if (ssid->wep_key_len[i] > 5) { - wpa_s->pairwise_cipher = WPA_CIPHER_WEP104; - wpa_s->group_cipher = WPA_CIPHER_WEP104; - break; - } else if (ssid->wep_key_len[i] > 0) { - wpa_s->pairwise_cipher = WPA_CIPHER_WEP40; - wpa_s->group_cipher = WPA_CIPHER_WEP40; - break; - } - } - - wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt); - wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE, - wpa_s->pairwise_cipher); - wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher); -#ifdef CONFIG_IEEE80211W - wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP, - wpa_s->mgmt_group_cipher); -#endif /* CONFIG_IEEE80211W */ - - pmksa_cache_clear_current(wpa_s->wpa); -} - - -static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s) -{ - scard_deinit(wpa_s->scard); - wpa_s->scard = NULL; - wpa_sm_set_scard_ctx(wpa_s->wpa, NULL); - eapol_sm_register_scard_ctx(wpa_s->eapol, NULL); - l2_packet_deinit(wpa_s->l2); - wpa_s->l2 = NULL; - if (wpa_s->l2_br) { - l2_packet_deinit(wpa_s->l2_br); - wpa_s->l2_br = NULL; - } - - if (wpa_s->ctrl_iface) { - wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface); - wpa_s->ctrl_iface = NULL; - } - if (wpa_s->conf != NULL) { - wpa_config_free(wpa_s->conf); - wpa_s->conf = NULL; - } - - os_free(wpa_s->confname); - wpa_s->confname = NULL; - - wpa_sm_set_eapol(wpa_s->wpa, NULL); - eapol_sm_deinit(wpa_s->eapol); - wpa_s->eapol = NULL; - - rsn_preauth_deinit(wpa_s->wpa); - - pmksa_candidate_free(wpa_s->wpa); - wpa_sm_deinit(wpa_s->wpa); - wpa_s->wpa = NULL; - wpa_blacklist_clear(wpa_s); - - os_free(wpa_s->scan_results); - wpa_s->scan_results = NULL; - wpa_s->num_scan_results = 0; - - wpa_supplicant_cancel_scan(wpa_s); - wpa_supplicant_cancel_auth_timeout(wpa_s); - - ieee80211_sta_deinit(wpa_s); -} - - -/** - * wpa_clear_keys - Clear keys configured for the driver - * @wpa_s: Pointer to wpa_supplicant data - * @addr: Previously used BSSID or %NULL if not available - * - * This function clears the encryption keys that has been previously configured - * for the driver. - */ -void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr) -{ - u8 *bcast = (u8 *) "\xff\xff\xff\xff\xff\xff"; - - if (wpa_s->keys_cleared) { - /* Some drivers (e.g., ndiswrapper & NDIS drivers) seem to have - * timing issues with keys being cleared just before new keys - * are set or just after association or something similar. This - * shows up in group key handshake failing often because of the - * client not receiving the first encrypted packets correctly. - * Skipping some of the extra key clearing steps seems to help - * in completing group key handshake more reliably. */ - wpa_printf(MSG_DEBUG, "No keys have been configured - " - "skip key clearing"); - return; - } - - /* MLME-DELETEKEYS.request */ - wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 0, 0, NULL, 0, NULL, 0); - wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 1, 0, NULL, 0, NULL, 0); - wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 2, 0, NULL, 0, NULL, 0); - wpa_drv_set_key(wpa_s, WPA_ALG_NONE, bcast, 3, 0, NULL, 0, NULL, 0); - if (addr) { - wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL, - 0); - /* MLME-SETPROTECTION.request(None) */ - wpa_drv_mlme_setprotection( - wpa_s, addr, - MLME_SETPROTECTION_PROTECT_TYPE_NONE, - MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); - } - wpa_s->keys_cleared = 1; -} - - -/** - * wpa_supplicant_state_txt - Get the connection state name as a text string - * @state: State (wpa_state; WPA_*) - * Returns: The state name as a printable text string - */ -const char * wpa_supplicant_state_txt(int state) -{ - switch (state) { - case WPA_DISCONNECTED: - return "DISCONNECTED"; - case WPA_INACTIVE: - return "INACTIVE"; - case WPA_SCANNING: - return "SCANNING"; - case WPA_ASSOCIATING: - return "ASSOCIATING"; - case WPA_ASSOCIATED: - return "ASSOCIATED"; - case WPA_4WAY_HANDSHAKE: - return "4WAY_HANDSHAKE"; - case WPA_GROUP_HANDSHAKE: - return "GROUP_HANDSHAKE"; - case WPA_COMPLETED: - return "COMPLETED"; - default: - return "UNKNOWN"; - } -} - - -/** - * wpa_supplicant_set_state - Set current connection state - * @wpa_s: Pointer to wpa_supplicant data - * @state: The new connection state - * - * This function is called whenever the connection state changes, e.g., - * association is completed for WPA/WPA2 4-Way Handshake is started. - */ -void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, wpa_states state) -{ - wpa_printf(MSG_DEBUG, "State: %s -> %s", - wpa_supplicant_state_txt(wpa_s->wpa_state), - wpa_supplicant_state_txt(state)); - - wpa_supplicant_dbus_notify_state_change(wpa_s, state, - wpa_s->wpa_state); - - if (state == WPA_COMPLETED && wpa_s->new_connection) { -#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG) - struct wpa_ssid *ssid = wpa_s->current_ssid; - wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to " - MACSTR " completed %s [id=%d id_str=%s]", - MAC2STR(wpa_s->bssid), wpa_s->reassociated_connection ? - "(reauth)" : "(auth)", - ssid ? ssid->id : -1, - ssid && ssid->id_str ? ssid->id_str : ""); -#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ - wpa_s->new_connection = 0; - wpa_s->reassociated_connection = 1; - wpa_drv_set_operstate(wpa_s, 1); - } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING || - state == WPA_ASSOCIATED) { - wpa_s->new_connection = 1; - wpa_drv_set_operstate(wpa_s, 0); - } - wpa_s->wpa_state = state; -} - - -/** - * wpa_supplicant_get_state - Get the connection state - * @wpa_s: Pointer to wpa_supplicant data - * Returns: The current connection state (WPA_*) - */ -wpa_states wpa_supplicant_get_state(struct wpa_supplicant *wpa_s) -{ - return wpa_s->wpa_state; -} - - -static void wpa_supplicant_terminate(int sig, void *eloop_ctx, - void *signal_ctx) -{ - struct wpa_global *global = eloop_ctx; - struct wpa_supplicant *wpa_s; - for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { - wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING "- signal %d " - "received", sig); - } - eloop_terminate(); -} - - -static void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s) -{ - wpa_s->pairwise_cipher = 0; - wpa_s->group_cipher = 0; - wpa_s->mgmt_group_cipher = 0; - wpa_s->key_mgmt = 0; - wpa_s->wpa_state = WPA_DISCONNECTED; -} - - -/** - * wpa_supplicant_reload_configuration - Reload configuration data - * @wpa_s: Pointer to wpa_supplicant data - * Returns: 0 on success or -1 if configuration parsing failed - * - * This function can be used to request that the configuration data is reloaded - * (e.g., after configuration file change). This function is reloading - * configuration only for one interface, so this may need to be called multiple - * times if %wpa_supplicant is controlling multiple interfaces and all - * interfaces need reconfiguration. - */ -int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s) -{ - struct wpa_config *conf; - int reconf_ctrl; - if (wpa_s->confname == NULL) - return -1; - conf = wpa_config_read(wpa_s->confname); - if (conf == NULL) { - wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration " - "file '%s' - exiting", wpa_s->confname); - return -1; - } - - reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface - || (conf->ctrl_interface && wpa_s->conf->ctrl_interface && - os_strcmp(conf->ctrl_interface, - wpa_s->conf->ctrl_interface) != 0); - - if (reconf_ctrl && wpa_s->ctrl_iface) { - wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface); - wpa_s->ctrl_iface = NULL; - } - - eapol_sm_invalidate_cached_session(wpa_s->eapol); - wpa_s->current_ssid = NULL; - /* - * TODO: should notify EAPOL SM about changes in opensc_engine_path, - * pkcs11_engine_path, pkcs11_module_path. - */ - if (wpa_s->key_mgmt == WPA_KEY_MGMT_PSK) { - /* - * Clear forced success to clear EAP state for next - * authentication. - */ - eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); - } - eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); - wpa_sm_set_config(wpa_s->wpa, NULL); - wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth); - rsn_preauth_deinit(wpa_s->wpa); - wpa_config_free(wpa_s->conf); - wpa_s->conf = conf; - if (reconf_ctrl) - wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s); - - wpa_supplicant_clear_status(wpa_s); - wpa_s->reassociate = 1; - wpa_supplicant_req_scan(wpa_s, 0, 0); - wpa_msg(wpa_s, MSG_DEBUG, "Reconfiguration completed"); - return 0; -} - - -static void wpa_supplicant_reconfig(int sig, void *eloop_ctx, - void *signal_ctx) -{ - struct wpa_global *global = eloop_ctx; - struct wpa_supplicant *wpa_s; - wpa_printf(MSG_DEBUG, "Signal %d received - reconfiguring", sig); - for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { - if (wpa_supplicant_reload_configuration(wpa_s) < 0) { - eloop_terminate(); - } - } -} - - -static void wpa_supplicant_gen_assoc_event(struct wpa_supplicant *wpa_s) -{ - struct wpa_ssid *ssid; - union wpa_event_data data; - - ssid = wpa_supplicant_get_ssid(wpa_s); - if (ssid == NULL) - return; - - if (wpa_s->current_ssid == NULL) - wpa_s->current_ssid = ssid; - wpa_supplicant_initiate_eapol(wpa_s); - wpa_printf(MSG_DEBUG, "Already associated with a configured network - " - "generating associated event"); - os_memset(&data, 0, sizeof(data)); - wpa_supplicant_event(wpa_s, EVENT_ASSOC, &data); -} - - -static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) -{ - struct wpa_supplicant *wpa_s = eloop_ctx; - struct wpa_ssid *ssid; - int enabled, scan_req = 0, ret; - - if (wpa_s->disconnected && !wpa_s->scan_req) - return; - - enabled = 0; - ssid = wpa_s->conf->ssid; - while (ssid) { - if (!ssid->disabled) { - enabled++; - break; - } - ssid = ssid->next; - } - if (!enabled && !wpa_s->scan_req) { - wpa_printf(MSG_DEBUG, "No enabled networks - do not scan"); - wpa_supplicant_set_state(wpa_s, WPA_INACTIVE); - return; - } - scan_req = wpa_s->scan_req; - wpa_s->scan_req = 0; - - if (wpa_s->conf->ap_scan != 0 && - wpa_s->driver && os_strcmp(wpa_s->driver->name, "wired") == 0) { - wpa_printf(MSG_DEBUG, "Using wired driver - overriding " - "ap_scan configuration"); - wpa_s->conf->ap_scan = 0; - } - - if (wpa_s->conf->ap_scan == 0) { - wpa_supplicant_gen_assoc_event(wpa_s); - return; - } - - if (wpa_s->wpa_state == WPA_DISCONNECTED || - wpa_s->wpa_state == WPA_INACTIVE) - wpa_supplicant_set_state(wpa_s, WPA_SCANNING); - - ssid = wpa_s->conf->ssid; - if (wpa_s->prev_scan_ssid != BROADCAST_SSID_SCAN) { - while (ssid) { - if (ssid == wpa_s->prev_scan_ssid) { - ssid = ssid->next; - break; - } - ssid = ssid->next; - } - } - while (ssid) { - if (!ssid->disabled && - (ssid->scan_ssid || wpa_s->conf->ap_scan == 2)) - break; - ssid = ssid->next; - } - - if (scan_req != 2 && wpa_s->conf->ap_scan == 2) { - /* - * ap_scan=2 mode - try to associate with each SSID instead of - * scanning for each scan_ssid=1 network. - */ - if (ssid == NULL) { - wpa_printf(MSG_DEBUG, "wpa_supplicant_scan: Reached " - "end of scan list - go back to beginning"); - wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN; - wpa_supplicant_req_scan(wpa_s, 0, 0); - return; - } - if (ssid->next) { - /* Continue from the next SSID on the next attempt. */ - wpa_s->prev_scan_ssid = ssid; - } else { - /* Start from the beginning of the SSID list. */ - wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN; - } - wpa_supplicant_associate(wpa_s, NULL, ssid); - return; - } - - wpa_printf(MSG_DEBUG, "Starting AP scan (%s SSID)", - ssid ? "specific": "broadcast"); - if (ssid) { - wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID", - ssid->ssid, ssid->ssid_len); - wpa_s->prev_scan_ssid = ssid; - } else - wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN; - - if (wpa_s->scan_res_tried == 0 && wpa_s->conf->ap_scan == 1) { - wpa_s->scan_res_tried++; - wpa_s->scan_req = scan_req; - wpa_printf(MSG_DEBUG, "Trying to get current scan results " - "first without requesting a new scan to speed up " - "initial association"); - wpa_supplicant_event(wpa_s, EVENT_SCAN_RESULTS, NULL); - return; - } - - if (wpa_s->use_client_mlme) { - ret = ieee80211_sta_req_scan(wpa_s, ssid ? ssid->ssid : NULL, - ssid ? ssid->ssid_len : 0); - } else { - ret = wpa_drv_scan(wpa_s, ssid ? ssid->ssid : NULL, - ssid ? ssid->ssid_len : 0); - } - if (ret) { - wpa_printf(MSG_WARNING, "Failed to initiate AP scan."); - wpa_supplicant_req_scan(wpa_s, 10, 0); - } -} - - -static wpa_cipher cipher_suite2driver(int cipher) -{ - switch (cipher) { - case WPA_CIPHER_NONE: - return CIPHER_NONE; - case WPA_CIPHER_WEP40: - return CIPHER_WEP40; - case WPA_CIPHER_WEP104: - return CIPHER_WEP104; - case WPA_CIPHER_CCMP: - return CIPHER_CCMP; - case WPA_CIPHER_TKIP: - default: - return CIPHER_TKIP; - } -} - - -static wpa_key_mgmt key_mgmt2driver(int key_mgmt) -{ - switch (key_mgmt) { - case WPA_KEY_MGMT_NONE: - return KEY_MGMT_NONE; - case WPA_KEY_MGMT_IEEE8021X_NO_WPA: - return KEY_MGMT_802_1X_NO_WPA; - case WPA_KEY_MGMT_IEEE8021X: - return KEY_MGMT_802_1X; - case WPA_KEY_MGMT_WPA_NONE: - return KEY_MGMT_WPA_NONE; - case WPA_KEY_MGMT_PSK: - default: - return KEY_MGMT_PSK; - } -} - - -static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s, - struct wpa_ssid *ssid, - struct wpa_ie_data *ie) -{ - int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie); - if (ret) { - if (ret == -2) { - wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE " - "from association info"); - } - return -1; - } - - wpa_printf(MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set cipher " - "suites"); - if (!(ie->group_cipher & ssid->group_cipher)) { - wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group " - "cipher 0x%x (mask 0x%x) - reject", - ie->group_cipher, ssid->group_cipher); - return -1; - } - if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) { - wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise " - "cipher 0x%x (mask 0x%x) - reject", - ie->pairwise_cipher, ssid->pairwise_cipher); - return -1; - } - if (!(ie->key_mgmt & ssid->key_mgmt)) { - wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key " - "management 0x%x (mask 0x%x) - reject", - ie->key_mgmt, ssid->key_mgmt); - return -1; - } - -#ifdef CONFIG_IEEE80211W - if (!(ie->capabilities & WPA_CAPABILITY_MGMT_FRAME_PROTECTION) && - ssid->ieee80211w == IEEE80211W_REQUIRED) { - wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP " - "that does not support management frame protection - " - "reject"); - return -1; - } -#endif /* CONFIG_IEEE80211W */ - - return 0; -} - - -/** - * wpa_supplicant_set_suites - Set authentication and encryption parameters - * @wpa_s: Pointer to wpa_supplicant data - * @bss: Scan results for the selected BSS, or %NULL if not available - * @ssid: Configuration data for the selected network - * @wpa_ie: Buffer for the WPA/RSN IE - * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the - * used buffer length in case the functions returns success. - * Returns: 0 on success or -1 on failure - * - * This function is used to configure authentication and encryption parameters - * based on the network configuration and scan result for the selected BSS (if - * available). - */ -int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, - struct wpa_scan_result *bss, - struct wpa_ssid *ssid, - u8 *wpa_ie, size_t *wpa_ie_len) -{ - struct wpa_ie_data ie; - int sel, proto; - - if (bss && bss->rsn_ie_len && (ssid->proto & WPA_PROTO_RSN) && - wpa_parse_wpa_ie(bss->rsn_ie, bss->rsn_ie_len, &ie) == 0 && - (ie.group_cipher & ssid->group_cipher) && - (ie.pairwise_cipher & ssid->pairwise_cipher) && - (ie.key_mgmt & ssid->key_mgmt)) { - wpa_msg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0"); - proto = WPA_PROTO_RSN; - } else if (bss && bss->wpa_ie_len && (ssid->proto & WPA_PROTO_WPA) && - wpa_parse_wpa_ie(bss->wpa_ie, bss->wpa_ie_len, &ie) == 0 && - (ie.group_cipher & ssid->group_cipher) && - (ie.pairwise_cipher & ssid->pairwise_cipher) && - (ie.key_mgmt & ssid->key_mgmt)) { - wpa_msg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0"); - proto = WPA_PROTO_WPA; - } else if (bss) { - wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN"); - return -1; - } else { - if (ssid->proto & WPA_PROTO_RSN) - proto = WPA_PROTO_RSN; - else - proto = WPA_PROTO_WPA; - if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) { - os_memset(&ie, 0, sizeof(ie)); - ie.group_cipher = ssid->group_cipher; - ie.pairwise_cipher = ssid->pairwise_cipher; - ie.key_mgmt = ssid->key_mgmt; -#ifdef CONFIG_IEEE80211W - ie.mgmt_group_cipher = - ssid->ieee80211w != NO_IEEE80211W ? - WPA_CIPHER_AES_128_CMAC : 0; -#endif /* CONFIG_IEEE80211W */ - wpa_printf(MSG_DEBUG, "WPA: Set cipher suites based " - "on configuration"); - } else - proto = ie.proto; - } - - wpa_printf(MSG_DEBUG, "WPA: Selected cipher suites: group %d " - "pairwise %d key_mgmt %d proto %d", - ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto); -#ifdef CONFIG_IEEE80211W - if (ssid->ieee80211w) { - wpa_printf(MSG_DEBUG, "WPA: Selected mgmt group cipher %d", - ie.mgmt_group_cipher); - } -#endif /* CONFIG_IEEE80211W */ - - wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto); - - if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss ? bss->wpa_ie : NULL, - bss ? bss->wpa_ie_len : 0) || - wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss ? bss->rsn_ie : NULL, - bss ? bss->rsn_ie_len : 0)) - return -1; - - sel = ie.group_cipher & ssid->group_cipher; - if (sel & WPA_CIPHER_CCMP) { - wpa_s->group_cipher = WPA_CIPHER_CCMP; - wpa_msg(wpa_s, MSG_DEBUG, "WPA: using GTK CCMP"); - } else if (sel & WPA_CIPHER_TKIP) { - wpa_s->group_cipher = WPA_CIPHER_TKIP; - wpa_msg(wpa_s, MSG_DEBUG, "WPA: using GTK TKIP"); - } else if (sel & WPA_CIPHER_WEP104) { - wpa_s->group_cipher = WPA_CIPHER_WEP104; - wpa_msg(wpa_s, MSG_DEBUG, "WPA: using GTK WEP104"); - } else if (sel & WPA_CIPHER_WEP40) { - wpa_s->group_cipher = WPA_CIPHER_WEP40; - wpa_msg(wpa_s, MSG_DEBUG, "WPA: using GTK WEP40"); - } else { - wpa_printf(MSG_WARNING, "WPA: Failed to select group cipher."); - return -1; - } - - sel = ie.pairwise_cipher & ssid->pairwise_cipher; - if (sel & WPA_CIPHER_CCMP) { - wpa_s->pairwise_cipher = WPA_CIPHER_CCMP; - wpa_msg(wpa_s, MSG_DEBUG, "WPA: using PTK CCMP"); - } else if (sel & WPA_CIPHER_TKIP) { - wpa_s->pairwise_cipher = WPA_CIPHER_TKIP; - wpa_msg(wpa_s, MSG_DEBUG, "WPA: using PTK TKIP"); - } else if (sel & WPA_CIPHER_NONE) { - wpa_s->pairwise_cipher = WPA_CIPHER_NONE; - wpa_msg(wpa_s, MSG_DEBUG, "WPA: using PTK NONE"); - } else { - wpa_printf(MSG_WARNING, "WPA: Failed to select pairwise " - "cipher."); - return -1; - } - - sel = ie.key_mgmt & ssid->key_mgmt; - if (sel & WPA_KEY_MGMT_IEEE8021X) { - wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X; - wpa_msg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X"); - } else if (sel & WPA_KEY_MGMT_PSK) { - wpa_s->key_mgmt = WPA_KEY_MGMT_PSK; - wpa_msg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK"); - } else if (sel & WPA_KEY_MGMT_WPA_NONE) { - wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE; - wpa_msg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE"); - } else { - wpa_printf(MSG_WARNING, "WPA: Failed to select authenticated " - "key management type."); - return -1; - } - - wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt); - wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE, - wpa_s->pairwise_cipher); - wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher); - -#ifdef CONFIG_IEEE80211W - sel = ie.mgmt_group_cipher; - if (ssid->ieee80211w == NO_IEEE80211W || - !(ie.capabilities & WPA_CAPABILITY_MGMT_FRAME_PROTECTION)) - sel = 0; - if (sel & WPA_CIPHER_AES_128_CMAC) { - wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC; - wpa_msg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher " - "AES-128-CMAC"); - } else { - wpa_s->mgmt_group_cipher = 0; - wpa_msg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher"); - } - wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP, - wpa_s->mgmt_group_cipher); -#endif /* CONFIG_IEEE80211W */ - - if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) { - wpa_printf(MSG_WARNING, "WPA: Failed to generate WPA IE."); - return -1; - } - - if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) - wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN); - else - wpa_sm_set_pmk_from_pmksa(wpa_s->wpa); - - return 0; -} - - -/** - * wpa_supplicant_associate - Request association - * @wpa_s: Pointer to wpa_supplicant data - * @bss: Scan results for the selected BSS, or %NULL if not available - * @ssid: Configuration data for the selected network - * - * This function is used to request %wpa_supplicant to associate with a BSS. - */ -void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, - struct wpa_scan_result *bss, - struct wpa_ssid *ssid) -{ - u8 wpa_ie[80]; - size_t wpa_ie_len; - int use_crypt, ret, i; - int algs = AUTH_ALG_OPEN_SYSTEM; - wpa_cipher cipher_pairwise, cipher_group; - struct wpa_driver_associate_params params; - int wep_keys_set = 0; - struct wpa_driver_capa capa; - int assoc_failed = 0; - - wpa_s->reassociate = 0; - if (bss) { - wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR - " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid), - wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq); - os_memset(wpa_s->bssid, 0, ETH_ALEN); - os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN); - } else { - wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'", - wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); - os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); - } - wpa_supplicant_cancel_scan(wpa_s); - - /* Starting new association, so clear the possibly used WPA IE from the - * previous association. */ - wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0); - -#ifdef IEEE8021X_EAPOL - if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) { - if (ssid->leap) { - if (ssid->non_leap == 0) - algs = AUTH_ALG_LEAP; - else - algs |= AUTH_ALG_LEAP; - } - } -#endif /* IEEE8021X_EAPOL */ - wpa_printf(MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs); - if (ssid->auth_alg) { - algs = 0; - if (ssid->auth_alg & WPA_AUTH_ALG_OPEN) - algs |= AUTH_ALG_OPEN_SYSTEM; - if (ssid->auth_alg & WPA_AUTH_ALG_SHARED) - algs |= AUTH_ALG_SHARED_KEY; - if (ssid->auth_alg & WPA_AUTH_ALG_LEAP) - algs |= AUTH_ALG_LEAP; - wpa_printf(MSG_DEBUG, "Overriding auth_alg selection: 0x%x", - algs); - } - wpa_drv_set_auth_alg(wpa_s, algs); - - if (bss && (bss->wpa_ie_len || bss->rsn_ie_len) && - (ssid->key_mgmt & (WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_PSK))) { - int try_opportunistic; - try_opportunistic = ssid->proactive_key_caching && - (ssid->proto & WPA_PROTO_RSN); - if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, - wpa_s->current_ssid, - try_opportunistic) == 0) - eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1); - wpa_ie_len = sizeof(wpa_ie); - if (wpa_supplicant_set_suites(wpa_s, bss, ssid, - wpa_ie, &wpa_ie_len)) { - wpa_printf(MSG_WARNING, "WPA: Failed to set WPA key " - "management and encryption suites"); - return; - } - } else if (ssid->key_mgmt & - (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_IEEE8021X | - WPA_KEY_MGMT_WPA_NONE)) { - wpa_ie_len = sizeof(wpa_ie); - if (wpa_supplicant_set_suites(wpa_s, NULL, ssid, - wpa_ie, &wpa_ie_len)) { - wpa_printf(MSG_WARNING, "WPA: Failed to set WPA key " - "management and encryption suites (no scan " - "results)"); - return; - } - } else { - wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); - wpa_ie_len = 0; - } - - wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL); - use_crypt = 1; - cipher_pairwise = cipher_suite2driver(wpa_s->pairwise_cipher); - cipher_group = cipher_suite2driver(wpa_s->group_cipher); - if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE || - wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { - if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) - use_crypt = 0; - for (i = 0; i < NUM_WEP_KEYS; i++) { - if (ssid->wep_key_len[i]) { - use_crypt = 1; - wep_keys_set = 1; - wpa_set_wep_key(wpa_s, - i == ssid->wep_tx_keyidx, - i, ssid->wep_key[i], - ssid->wep_key_len[i]); - } - } - } - -#ifdef IEEE8021X_EAPOL - if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { - if ((ssid->eapol_flags & - (EAPOL_FLAG_REQUIRE_KEY_UNICAST | - EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 && - !wep_keys_set) { - use_crypt = 0; - } else { - /* Assume that dynamic WEP-104 keys will be used and - * set cipher suites in order for drivers to expect - * encryption. */ - cipher_pairwise = cipher_group = CIPHER_WEP104; - } - } -#endif /* IEEE8021X_EAPOL */ - - if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) { - /* Set the key before (and later after) association */ - wpa_supplicant_set_wpa_none_key(wpa_s, ssid); - } - - wpa_drv_set_drop_unencrypted(wpa_s, use_crypt); - wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING); - os_memset(¶ms, 0, sizeof(params)); - if (bss) { - params.bssid = bss->bssid; - params.ssid = bss->ssid; - params.ssid_len = bss->ssid_len; - params.freq = bss->freq; - } else { - params.ssid = ssid->ssid; - params.ssid_len = ssid->ssid_len; - } - if (ssid->mode == 1 && ssid->frequency > 0 && params.freq == 0) - params.freq = ssid->frequency; /* Initial channel for IBSS */ - params.wpa_ie = wpa_ie; - params.wpa_ie_len = wpa_ie_len; - params.pairwise_suite = cipher_pairwise; - params.group_suite = cipher_group; - params.key_mgmt_suite = key_mgmt2driver(wpa_s->key_mgmt); - params.auth_alg = algs; - params.mode = ssid->mode; - for (i = 0; i < NUM_WEP_KEYS; i++) { - if (ssid->wep_key_len[i]) - params.wep_key[i] = ssid->wep_key[i]; - params.wep_key_len[i] = ssid->wep_key_len[i]; - } - params.wep_tx_keyidx = ssid->wep_tx_keyidx; - -#ifdef CONFIG_IEEE80211W - switch (ssid->ieee80211w) { - case NO_IEEE80211W: - params.mgmt_frame_protection = NO_MGMT_FRAME_PROTECTION; - break; - case IEEE80211W_OPTIONAL: - params.mgmt_frame_protection = MGMT_FRAME_PROTECTION_OPTIONAL; - break; - case IEEE80211W_REQUIRED: - params.mgmt_frame_protection = MGMT_FRAME_PROTECTION_REQUIRED; - break; - } -#endif /* CONFIG_IEEE80211W */ - - if (wpa_s->use_client_mlme) - ret = ieee80211_sta_associate(wpa_s, ¶ms); - else - ret = wpa_drv_associate(wpa_s, ¶ms); - if (ret < 0) { - wpa_msg(wpa_s, MSG_INFO, "Association request to the driver " - "failed"); - /* try to continue anyway; new association will be tried again - * after timeout */ - assoc_failed = 1; - } - - if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) { - /* Set the key after the association just in case association - * cleared the previously configured key. */ - wpa_supplicant_set_wpa_none_key(wpa_s, ssid); - /* No need to timeout authentication since there is no key - * management. */ - wpa_supplicant_cancel_auth_timeout(wpa_s); - wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); - } else { - /* Timeout for IEEE 802.11 authentication and association */ - int timeout = 60; - - if (assoc_failed) { - /* give IBSS a bit more time */ - timeout = ssid->mode ? 10 : 5; - } else if (wpa_s->conf->ap_scan == 1) { - /* give IBSS a bit more time */ - timeout = ssid->mode ? 20 : 10; - } - wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0); - } - - if (wep_keys_set && wpa_drv_get_capa(wpa_s, &capa) == 0 && - capa.flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC) { - /* Set static WEP keys again */ - int j; - for (j = 0; j < NUM_WEP_KEYS; j++) { - if (ssid->wep_key_len[j]) { - wpa_set_wep_key(wpa_s, - j == ssid->wep_tx_keyidx, - j, ssid->wep_key[j], - ssid->wep_key_len[j]); - } - } - } - - if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) { - /* - * Do not allow EAP session resumption between different - * network configurations. - */ - eapol_sm_invalidate_cached_session(wpa_s->eapol); - } - wpa_s->current_ssid = ssid; - wpa_sm_set_config(wpa_s->wpa, wpa_s->current_ssid); - wpa_supplicant_initiate_eapol(wpa_s); -} - - -/** - * wpa_supplicant_disassociate - Disassociate the current connection - * @wpa_s: Pointer to wpa_supplicant data - * @reason_code: IEEE 802.11 reason code for the disassociate frame - * - * This function is used to request %wpa_supplicant to disassociate with the - * current AP. - */ -void wpa_supplicant_disassociate(struct wpa_supplicant *wpa_s, - int reason_code) -{ - u8 *addr = NULL; - if (os_memcmp(wpa_s->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) != 0) - { - if (wpa_s->use_client_mlme) - ieee80211_sta_disassociate(wpa_s, reason_code); - else - wpa_drv_disassociate(wpa_s, wpa_s->bssid, reason_code); - addr = wpa_s->bssid; - } - wpa_clear_keys(wpa_s, addr); - wpa_supplicant_mark_disassoc(wpa_s); - wpa_s->current_ssid = NULL; - wpa_sm_set_config(wpa_s->wpa, NULL); - eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); -} - - -/** - * wpa_supplicant_deauthenticate - Deauthenticate the current connection - * @wpa_s: Pointer to wpa_supplicant data - * @reason_code: IEEE 802.11 reason code for the deauthenticate frame - * - * This function is used to request %wpa_supplicant to disassociate with the - * current AP. - */ -void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s, - int reason_code) -{ - u8 *addr = NULL; - wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); - if (os_memcmp(wpa_s->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) != 0) - { - if (wpa_s->use_client_mlme) - ieee80211_sta_deauthenticate(wpa_s, reason_code); - else - wpa_drv_deauthenticate(wpa_s, wpa_s->bssid, - reason_code); - addr = wpa_s->bssid; - } - wpa_clear_keys(wpa_s, addr); - wpa_s->current_ssid = NULL; - wpa_sm_set_config(wpa_s->wpa, NULL); - eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); - eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); - eapol_sm_notify_portValid(wpa_s->eapol, FALSE); -} - - -/** - * wpa_supplicant_get_scan_results - Get scan results - * @wpa_s: Pointer to wpa_supplicant data - * Returns: 0 on success, -1 on failure - * - * This function is request the current scan results from the driver and stores - * a local copy of the results in wpa_s->scan_results. - */ -int wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s) -{ -#define SCAN_AP_LIMIT 128 - struct wpa_scan_result *results, *tmp; - int num; - - results = os_malloc(SCAN_AP_LIMIT * sizeof(struct wpa_scan_result)); - if (results == NULL) { - wpa_printf(MSG_WARNING, "Failed to allocate memory for scan " - "results"); - return -1; - } - - if (wpa_s->use_client_mlme) { - num = ieee80211_sta_get_scan_results(wpa_s, results, - SCAN_AP_LIMIT); - } else - num = wpa_drv_get_scan_results(wpa_s, results, SCAN_AP_LIMIT); - wpa_printf(MSG_DEBUG, "Scan results: %d", num); - if (num < 0) { - wpa_printf(MSG_DEBUG, "Failed to get scan results"); - os_free(results); - return -1; - } - if (num > SCAN_AP_LIMIT) { - wpa_printf(MSG_INFO, "Not enough room for all APs (%d < %d)", - num, SCAN_AP_LIMIT); - num = SCAN_AP_LIMIT; - } - - /* Free unneeded memory for unused scan result entries */ - tmp = os_realloc(results, num * sizeof(struct wpa_scan_result)); - if (tmp || num == 0) { - results = tmp; - } - - os_free(wpa_s->scan_results); - wpa_s->scan_results = results; - wpa_s->num_scan_results = num; - - return 0; -} - - -#ifndef CONFIG_NO_WPA -static int wpa_get_beacon_ie(struct wpa_supplicant *wpa_s) -{ - int i, ret = 0; - struct wpa_scan_result *results, *curr = NULL; - - results = wpa_s->scan_results; - if (results == NULL) { - return -1; - } - - for (i = 0; i < wpa_s->num_scan_results; i++) { - struct wpa_ssid *ssid = wpa_s->current_ssid; - if (os_memcmp(results[i].bssid, wpa_s->bssid, ETH_ALEN) != 0) - continue; - if (ssid == NULL || - ((results[i].ssid_len == ssid->ssid_len && - os_memcmp(results[i].ssid, ssid->ssid, ssid->ssid_len) - == 0) || - ssid->ssid_len == 0)) { - curr = &results[i]; - break; - } - } - - if (curr) { - if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, curr->wpa_ie, - curr->wpa_ie_len) || - wpa_sm_set_ap_rsn_ie(wpa_s->wpa, curr->rsn_ie, - curr->rsn_ie_len)) - ret = -1; - } else { - ret = -1; - } - - return ret; -} - - -static int wpa_supplicant_get_beacon_ie(void *ctx) -{ - struct wpa_supplicant *wpa_s = ctx; - if (wpa_get_beacon_ie(wpa_s) == 0) { - return 0; - } - - /* No WPA/RSN IE found in the cached scan results. Try to get updated - * scan results from the driver. */ - if (wpa_supplicant_get_scan_results(wpa_s) < 0) { - return -1; - } - - return wpa_get_beacon_ie(wpa_s); -} -#endif /* CONFIG_NO_WPA */ - - -/** - * wpa_supplicant_get_ssid - Get a pointer to the current network structure - * @wpa_s: Pointer to wpa_supplicant data - * Returns: A pointer to the current network structure or %NULL on failure - */ -struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s) -{ - struct wpa_ssid *entry; - u8 ssid[MAX_SSID_LEN]; - int res; - size_t ssid_len; - u8 bssid[ETH_ALEN]; - int wired; - - if (wpa_s->use_client_mlme) { - if (ieee80211_sta_get_ssid(wpa_s, ssid, &ssid_len)) { - wpa_printf(MSG_WARNING, "Could not read SSID from " - "MLME."); - return NULL; - } - } else { - res = wpa_drv_get_ssid(wpa_s, ssid); - if (res < 0) { - wpa_printf(MSG_WARNING, "Could not read SSID from " - "driver."); - return NULL; - } - ssid_len = res; - } - - if (wpa_s->use_client_mlme) - os_memcpy(bssid, wpa_s->bssid, ETH_ALEN); - else if (wpa_drv_get_bssid(wpa_s, bssid) < 0) { - wpa_printf(MSG_WARNING, "Could not read BSSID from driver."); - return NULL; - } - - wired = wpa_s->conf->ap_scan == 0 && wpa_s->driver && - os_strcmp(wpa_s->driver->name, "wired") == 0; - - entry = wpa_s->conf->ssid; - while (entry) { - if (!entry->disabled && - ((ssid_len == entry->ssid_len && - os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) && - (!entry->bssid_set || - os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)) - return entry; - entry = entry->next; - } - - return NULL; -} - - -#ifndef CONFIG_NO_WPA -static u8 * _wpa_alloc_eapol(void *wpa_s, u8 type, - const void *data, u16 data_len, - size_t *msg_len, void **data_pos) -{ - return wpa_alloc_eapol(wpa_s, type, data, data_len, msg_len, data_pos); -} - - -static int _wpa_ether_send(void *wpa_s, const u8 *dest, u16 proto, - const u8 *buf, size_t len) -{ - return wpa_ether_send(wpa_s, dest, proto, buf, len); -} - - -static void _wpa_supplicant_cancel_auth_timeout(void *wpa_s) -{ - wpa_supplicant_cancel_auth_timeout(wpa_s); -} - - -static void _wpa_supplicant_set_state(void *wpa_s, wpa_states state) -{ - wpa_supplicant_set_state(wpa_s, state); -} - - -static wpa_states _wpa_supplicant_get_state(void *wpa_s) -{ - return wpa_supplicant_get_state(wpa_s); -} - - -static void _wpa_supplicant_disassociate(void *wpa_s, int reason_code) -{ - wpa_supplicant_disassociate(wpa_s, reason_code); - /* Schedule a scan to make sure we continue looking for networks */ - wpa_supplicant_req_scan(wpa_s, 0, 0); -} - - -static void _wpa_supplicant_deauthenticate(void *wpa_s, int reason_code) -{ - wpa_supplicant_deauthenticate(wpa_s, reason_code); - /* Schedule a scan to make sure we continue looking for networks */ - wpa_supplicant_req_scan(wpa_s, 0, 0); -} - - -static struct wpa_ssid * _wpa_supplicant_get_ssid(void *wpa_s) -{ - return wpa_supplicant_get_ssid(wpa_s); -} - - -static int wpa_supplicant_get_bssid(void *ctx, u8 *bssid) -{ - struct wpa_supplicant *wpa_s = ctx; - if (wpa_s->use_client_mlme) { - os_memcpy(bssid, wpa_s->bssid, ETH_ALEN); - return 0; - } - return wpa_drv_get_bssid(wpa_s, bssid); -} - - -static int wpa_supplicant_set_key(void *wpa_s, 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) -{ - return wpa_drv_set_key(wpa_s, alg, addr, key_idx, set_tx, seq, seq_len, - key, key_len); -} - - -static int wpa_supplicant_mlme_setprotection(void *wpa_s, const u8 *addr, - int protection_type, - int key_type) -{ - return wpa_drv_mlme_setprotection(wpa_s, addr, protection_type, - key_type); -} - - -static int wpa_supplicant_add_pmkid(void *wpa_s, - const u8 *bssid, const u8 *pmkid) -{ - return wpa_drv_add_pmkid(wpa_s, bssid, pmkid); -} - - -static int wpa_supplicant_remove_pmkid(void *wpa_s, - const u8 *bssid, const u8 *pmkid) -{ - return wpa_drv_remove_pmkid(wpa_s, bssid, pmkid); -} -#endif /* CONFIG_NO_WPA */ - - -static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s, - const char *name) -{ - int i; - - if (wpa_s == NULL) - return -1; - - if (wpa_supplicant_drivers[0] == NULL) { - wpa_printf(MSG_ERROR, "No driver interfaces build into " - "wpa_supplicant."); - return -1; - } - - if (name == NULL) { - /* default to first driver in the list */ - wpa_s->driver = wpa_supplicant_drivers[0]; - return 0; - } - - for (i = 0; wpa_supplicant_drivers[i]; i++) { - if (os_strcmp(name, wpa_supplicant_drivers[i]->name) == 0) { - wpa_s->driver = wpa_supplicant_drivers[i]; - return 0; - } - } - - wpa_printf(MSG_ERROR, "Unsupported driver '%s'.\n", name); - return -1; -} - - -void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len) -{ - struct wpa_supplicant *wpa_s = ctx; - - wpa_printf(MSG_DEBUG, "RX EAPOL from " MACSTR, MAC2STR(src_addr)); - wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len); - - if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) { - wpa_printf(MSG_DEBUG, "Ignored received EAPOL frame since " - "no key management is configured"); - return; - } - - if (wpa_s->eapol_received == 0) { - /* Timeout for completing IEEE 802.1X and WPA authentication */ - wpa_supplicant_req_auth_timeout( - wpa_s, - (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X || - wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) ? - 70 : 10, 0); - } - wpa_s->eapol_received++; - - if (wpa_s->countermeasures) { - wpa_printf(MSG_INFO, "WPA: Countermeasures - dropped EAPOL " - "packet"); - return; - } - - /* Source address of the incoming EAPOL frame could be compared to the - * current BSSID. However, it is possible that a centralized - * Authenticator could be using another MAC address than the BSSID of - * an AP, so just allow any address to be used for now. The replies are - * still sent to the current BSSID (if available), though. */ - - os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN); - if (wpa_s->key_mgmt != WPA_KEY_MGMT_PSK && - eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0) - return; - wpa_drv_poll(wpa_s); - wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len); -} - - -/** - * wpa_supplicant_driver_init - Initialize driver interface parameters - * @wpa_s: Pointer to wpa_supplicant data - * @wait_for_interface: 0 = do not wait for the interface (reports a failure if - * the interface is not present), 1 = wait until the interface is available - * Returns: 0 on success, -1 on failure - * - * This function is called to initialize driver interface parameters. - * wpa_drv_init() must have been called before this function to initialize the - * driver interface. - */ -int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s, - int wait_for_interface) -{ - static int interface_count = 0; - - for (;;) { - if (wpa_s->driver->send_eapol) { - const u8 *addr = wpa_drv_get_mac_addr(wpa_s); - if (addr) - os_memcpy(wpa_s->own_addr, addr, ETH_ALEN); - break; - } - wpa_s->l2 = l2_packet_init(wpa_s->ifname, - wpa_drv_get_mac_addr(wpa_s), - ETH_P_EAPOL, - wpa_supplicant_rx_eapol, wpa_s, 0); - if (wpa_s->l2) - break; - else if (!wait_for_interface) - return -1; - wpa_printf(MSG_DEBUG, "Waiting for interface.."); - os_sleep(5, 0); - } - - if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) { - wpa_printf(MSG_ERROR, "Failed to get own L2 address"); - return -1; - } - - wpa_printf(MSG_DEBUG, "Own MAC address: " MACSTR, - MAC2STR(wpa_s->own_addr)); - - if (wpa_s->bridge_ifname[0]) { - wpa_printf(MSG_DEBUG, "Receiving packets from bridge interface" - " '%s'", wpa_s->bridge_ifname); - wpa_s->l2_br = l2_packet_init(wpa_s->bridge_ifname, - wpa_s->own_addr, - ETH_P_EAPOL, - wpa_supplicant_rx_eapol, wpa_s, - 0); - if (wpa_s->l2_br == NULL) { - wpa_printf(MSG_ERROR, "Failed to open l2_packet " - "connection for the bridge interface '%s'", - wpa_s->bridge_ifname); - return -1; - } - } - - /* Backwards compatibility call to set_wpa() handler. This is called - * only just after init and just before deinit, so these handler can be - * used to implement same functionality. */ - if (wpa_drv_set_wpa(wpa_s, 1) < 0) { - struct wpa_driver_capa capa; - if (wpa_drv_get_capa(wpa_s, &capa) < 0 || - !(capa.flags & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2))) { - wpa_printf(MSG_DEBUG, "Driver does not support WPA."); - /* Continue to allow non-WPA modes to be used. */ - } else { - wpa_printf(MSG_ERROR, "Failed to enable WPA in the " - "driver."); - return -1; - } - } - - wpa_clear_keys(wpa_s, NULL); - - /* Make sure that TKIP countermeasures are not left enabled (could - * happen if wpa_supplicant is killed during countermeasures. */ - wpa_drv_set_countermeasures(wpa_s, 0); - - wpa_drv_set_drop_unencrypted(wpa_s, 1); - - wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN; - wpa_supplicant_req_scan(wpa_s, interface_count, 100000); - interface_count++; - - return 0; -} - - -static int wpa_supplicant_daemon(const char *pid_file) -{ - wpa_printf(MSG_DEBUG, "Daemonize.."); - return os_daemonize(pid_file); -} - - -static struct wpa_supplicant * wpa_supplicant_alloc(void) -{ - struct wpa_supplicant *wpa_s; - - wpa_s = os_zalloc(sizeof(*wpa_s)); - if (wpa_s == NULL) - return NULL; - wpa_s->scan_req = 1; - - return wpa_s; -} - - -static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, - struct wpa_interface *iface) -{ - wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver " - "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname, - iface->confname ? iface->confname : "N/A", - iface->driver ? iface->driver : "default", - iface->ctrl_interface ? iface->ctrl_interface : "N/A", - iface->bridge_ifname ? iface->bridge_ifname : "N/A"); - - if (wpa_supplicant_set_driver(wpa_s, iface->driver) < 0) { - return -1; - } - - if (iface->confname) { -#ifdef CONFIG_BACKEND_FILE - wpa_s->confname = os_rel2abs_path(iface->confname); - if (wpa_s->confname == NULL) { - wpa_printf(MSG_ERROR, "Failed to get absolute path " - "for configuration file '%s'.", - iface->confname); - return -1; - } - wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'", - iface->confname, wpa_s->confname); -#else /* CONFIG_BACKEND_FILE */ - wpa_s->confname = os_strdup(iface->confname); -#endif /* CONFIG_BACKEND_FILE */ - wpa_s->conf = wpa_config_read(wpa_s->confname); - if (wpa_s->conf == NULL) { - wpa_printf(MSG_ERROR, "Failed to read or parse " - "configuration '%s'.", wpa_s->confname); - return -1; - } - - /* - * Override ctrl_interface and driver_param if set on command - * line. - */ - if (iface->ctrl_interface) { - os_free(wpa_s->conf->ctrl_interface); - wpa_s->conf->ctrl_interface = - os_strdup(iface->ctrl_interface); - } - - if (iface->driver_param) { - os_free(wpa_s->conf->driver_param); - wpa_s->conf->driver_param = - os_strdup(iface->driver_param); - } - } else - wpa_s->conf = wpa_config_alloc_empty(iface->ctrl_interface, - iface->driver_param); - - if (wpa_s->conf == NULL) { - wpa_printf(MSG_ERROR, "\nNo configuration found."); - return -1; - } - - if (iface->ifname == NULL) { - wpa_printf(MSG_ERROR, "\nInterface name is required."); - return -1; - } - if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) { - wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.", - iface->ifname); - return -1; - } - os_strncpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname)); - - if (iface->bridge_ifname) { - if (os_strlen(iface->bridge_ifname) >= - sizeof(wpa_s->bridge_ifname)) { - wpa_printf(MSG_ERROR, "\nToo long bridge interface " - "name '%s'.", iface->bridge_ifname); - return -1; - } - os_strncpy(wpa_s->bridge_ifname, iface->bridge_ifname, - sizeof(wpa_s->bridge_ifname)); - } - - return 0; -} - - -static int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s) -{ -#ifdef IEEE8021X_EAPOL - struct eapol_ctx *ctx; - ctx = os_zalloc(sizeof(*ctx)); - if (ctx == NULL) { - wpa_printf(MSG_ERROR, "Failed to allocate EAPOL context."); - return -1; - } - - ctx->ctx = wpa_s; - ctx->msg_ctx = wpa_s; - ctx->eapol_send_ctx = wpa_s; - ctx->preauth = 0; - ctx->eapol_done_cb = wpa_supplicant_notify_eapol_done; - ctx->eapol_send = wpa_supplicant_eapol_send; - ctx->set_wep_key = wpa_eapol_set_wep_key; - ctx->set_config_blob = wpa_supplicant_set_config_blob; - ctx->get_config_blob = wpa_supplicant_get_config_blob; - ctx->aborted_cached = wpa_supplicant_aborted_cached; - ctx->opensc_engine_path = wpa_s->conf->opensc_engine_path; - ctx->pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path; - ctx->pkcs11_module_path = wpa_s->conf->pkcs11_module_path; - wpa_s->eapol = eapol_sm_init(ctx); - if (wpa_s->eapol == NULL) { - os_free(ctx); - wpa_printf(MSG_ERROR, "Failed to initialize EAPOL state " - "machines."); - return -1; - } -#endif /* IEEE8021X_EAPOL */ - - return 0; -} - - -static int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s) -{ -#ifndef CONFIG_NO_WPA - struct wpa_sm_ctx *ctx; - ctx = os_zalloc(sizeof(*ctx)); - if (ctx == NULL) { - wpa_printf(MSG_ERROR, "Failed to allocate WPA context."); - return -1; - } - - ctx->ctx = wpa_s; - ctx->set_state = _wpa_supplicant_set_state; - ctx->get_state = _wpa_supplicant_get_state; - ctx->deauthenticate = _wpa_supplicant_deauthenticate; - ctx->disassociate = _wpa_supplicant_disassociate; - ctx->set_key = wpa_supplicant_set_key; - ctx->scan = wpa_supplicant_scan; - ctx->get_ssid = _wpa_supplicant_get_ssid; - ctx->get_bssid = wpa_supplicant_get_bssid; - ctx->ether_send = _wpa_ether_send; - ctx->get_beacon_ie = wpa_supplicant_get_beacon_ie; - ctx->alloc_eapol = _wpa_alloc_eapol; - ctx->cancel_auth_timeout = _wpa_supplicant_cancel_auth_timeout; - ctx->add_pmkid = wpa_supplicant_add_pmkid; - ctx->remove_pmkid = wpa_supplicant_remove_pmkid; - ctx->set_config_blob = wpa_supplicant_set_config_blob; - ctx->get_config_blob = wpa_supplicant_get_config_blob; - ctx->mlme_setprotection = wpa_supplicant_mlme_setprotection; - - wpa_s->wpa = wpa_sm_init(ctx); - if (wpa_s->wpa == NULL) { - wpa_printf(MSG_ERROR, "Failed to initialize WPA state " - "machine"); - return -1; - } -#endif /* CONFIG_NO_WPA */ - - return 0; -} - - -static int wpa_supplicant_init_iface2(struct wpa_supplicant *wpa_s, - int wait_for_interface) -{ - const char *ifname; - struct wpa_driver_capa capa; - - wpa_printf(MSG_DEBUG, "Initializing interface (2) '%s'", - wpa_s->ifname); - - if (wpa_supplicant_init_eapol(wpa_s) < 0) - return -1; - - /* RSNA Supplicant Key Management - INITIALIZE */ - eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); - eapol_sm_notify_portValid(wpa_s->eapol, FALSE); - - /* Initialize driver interface and register driver event handler before - * L2 receive handler so that association events are processed before - * EAPOL-Key packets if both become available for the same select() - * call. */ - wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname); - if (wpa_s->drv_priv == NULL) { - wpa_printf(MSG_ERROR, "Failed to initialize driver interface"); - return -1; - } - if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) { - wpa_printf(MSG_ERROR, "Driver interface rejected " - "driver_param '%s'", wpa_s->conf->driver_param); - return -1; - } - - ifname = wpa_drv_get_ifname(wpa_s); - if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) { - wpa_printf(MSG_DEBUG, "Driver interface replaced interface " - "name with '%s'", ifname); - os_strncpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname)); - } - - if (wpa_supplicant_init_wpa(wpa_s) < 0) - return -1; - - wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname, - wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname : - NULL); - wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth); - wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol); - - if (wpa_s->conf->dot11RSNAConfigPMKLifetime && - wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, - wpa_s->conf->dot11RSNAConfigPMKLifetime)) { - wpa_printf(MSG_ERROR, "Invalid WPA parameter value for " - "dot11RSNAConfigPMKLifetime"); - return -1; - } - - if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold && - wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, - wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) { - wpa_printf(MSG_ERROR, "Invalid WPA parameter value for " - "dot11RSNAConfigPMKReauthThreshold"); - return -1; - } - - if (wpa_s->conf->dot11RSNAConfigSATimeout && - wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, - wpa_s->conf->dot11RSNAConfigSATimeout)) { - wpa_printf(MSG_ERROR, "Invalid WPA parameter value for " - "dot11RSNAConfigSATimeout"); - return -1; - } - - if (wpa_supplicant_driver_init(wpa_s, wait_for_interface) < 0) { - return -1; - } - wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr); - - wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s); - if (wpa_s->ctrl_iface == NULL) { - wpa_printf(MSG_ERROR, - "Failed to initialize control interface '%s'.\n" - "You may have another wpa_supplicant process " - "already running or the file was\n" - "left by an unclean termination of wpa_supplicant " - "in which case you will need\n" - "to manually remove this file before starting " - "wpa_supplicant again.\n", - wpa_s->conf->ctrl_interface); - return -1; - } - - if (wpa_drv_get_capa(wpa_s, &capa) == 0 && - capa.flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME) { - wpa_s->use_client_mlme = 1; - if (ieee80211_sta_init(wpa_s)) - return -1; - } - - return 0; -} - - -static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s) -{ - if (wpa_s->drv_priv) { - wpa_supplicant_deauthenticate(wpa_s, REASON_DEAUTH_LEAVING); - - /* Backwards compatibility call to set_wpa() handler. This is - * called only just after init and just before deinit, so these - * handler can be used to implement same functionality. */ - if (wpa_drv_set_wpa(wpa_s, 0) < 0) { - wpa_printf(MSG_ERROR, "Failed to disable WPA in the " - "driver."); - } - - wpa_drv_set_drop_unencrypted(wpa_s, 0); - wpa_drv_set_countermeasures(wpa_s, 0); - wpa_clear_keys(wpa_s, NULL); - } - - wpas_dbus_unregister_iface(wpa_s); - - wpa_supplicant_cleanup(wpa_s); - - if (wpa_s->drv_priv) - wpa_drv_deinit(wpa_s); -} - - -/** - * wpa_supplicant_add_iface - Add a new network interface - * @global: Pointer to global data from wpa_supplicant_init() - * @iface: Interface configuration options - * Returns: Pointer to the created interface or %NULL on failure - * - * This function is used to add new network interfaces for %wpa_supplicant. - * This can be called before wpa_supplicant_run() to add interfaces before the - * main event loop has been started. In addition, new interfaces can be added - * dynamically while %wpa_supplicant is already running. This could happen, - * e.g., when a hotplug network adapter is inserted. - */ -struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global, - struct wpa_interface *iface) -{ - struct wpa_supplicant *wpa_s; - - if (global == NULL || iface == NULL) - return NULL; - - wpa_s = wpa_supplicant_alloc(); - if (wpa_s == NULL) - return NULL; - - if (wpa_supplicant_init_iface(wpa_s, iface) || - wpa_supplicant_init_iface2(wpa_s, - global->params.wait_for_interface)) { - wpa_printf(MSG_DEBUG, "Failed to add interface %s", - iface->ifname); - wpa_supplicant_deinit_iface(wpa_s); - os_free(wpa_s); - return NULL; - } - - wpa_s->global = global; - - /* Register the interface with the dbus control interface */ - if (wpas_dbus_register_iface(wpa_s)) { - wpa_supplicant_deinit_iface(wpa_s); - os_free(wpa_s); - return NULL; - } - - wpa_s->next = global->ifaces; - global->ifaces = wpa_s; - - wpa_printf(MSG_DEBUG, "Added interface %s", wpa_s->ifname); - - return wpa_s; -} - - -/** - * wpa_supplicant_remove_iface - Remove a network interface - * @global: Pointer to global data from wpa_supplicant_init() - * @wpa_s: Pointer to the network interface to be removed - * Returns: 0 if interface was removed, -1 if interface was not found - * - * This function can be used to dynamically remove network interfaces from - * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In - * addition, this function is used to remove all remaining interfaces when - * %wpa_supplicant is terminated. - */ -int wpa_supplicant_remove_iface(struct wpa_global *global, - struct wpa_supplicant *wpa_s) -{ - struct wpa_supplicant *prev; - - /* Remove interface from the global list of interfaces */ - prev = global->ifaces; - if (prev == wpa_s) { - global->ifaces = wpa_s->next; - } else { - while (prev && prev->next != wpa_s) - prev = prev->next; - if (prev == NULL) - return -1; - prev->next = wpa_s->next; - } - - wpa_printf(MSG_DEBUG, "Removing interface %s", wpa_s->ifname); - - wpa_supplicant_deinit_iface(wpa_s); - os_free(wpa_s); - - return 0; -} - - -/** - * wpa_supplicant_get_iface - Get a new network interface - * @global: Pointer to global data from wpa_supplicant_init() - * @ifname: Interface name - * Returns: Pointer to the interface or %NULL if not found - */ -struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global, - const char *ifname) -{ - struct wpa_supplicant *wpa_s; - - for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { - if (os_strcmp(wpa_s->ifname, ifname) == 0) - return wpa_s; - } - return NULL; -} - - -/** - * wpa_supplicant_init - Initialize %wpa_supplicant - * @params: Parameters for %wpa_supplicant - * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure - * - * This function is used to initialize %wpa_supplicant. After successful - * initialization, the returned data pointer can be used to add and remove - * network interfaces, and eventually, to deinitialize %wpa_supplicant. - */ -struct wpa_global * wpa_supplicant_init(struct wpa_params *params) -{ - struct wpa_global *global; - int ret; - - if (params == NULL) - return NULL; - - wpa_debug_open_file(params->wpa_debug_file_path); - if (params->wpa_debug_syslog) - wpa_debug_open_syslog(); - - ret = eap_peer_register_methods(); - if (ret) { - wpa_printf(MSG_ERROR, "Failed to register EAP methods"); - if (ret == -2) - wpa_printf(MSG_ERROR, "Two or more EAP methods used " - "the same EAP type."); - return NULL; - } - - global = os_zalloc(sizeof(*global)); - if (global == NULL) - return NULL; - global->params.daemonize = params->daemonize; - global->params.wait_for_interface = params->wait_for_interface; - global->params.wait_for_monitor = params->wait_for_monitor; - global->params.dbus_ctrl_interface = params->dbus_ctrl_interface; - if (params->pid_file) - global->params.pid_file = os_strdup(params->pid_file); - if (params->ctrl_interface) - global->params.ctrl_interface = - os_strdup(params->ctrl_interface); - wpa_debug_level = global->params.wpa_debug_level = - params->wpa_debug_level; - wpa_debug_show_keys = global->params.wpa_debug_show_keys = - params->wpa_debug_show_keys; - wpa_debug_timestamp = global->params.wpa_debug_timestamp = - params->wpa_debug_timestamp; - - if (eloop_init(global)) { - wpa_printf(MSG_ERROR, "Failed to initialize event loop"); - wpa_supplicant_deinit(global); - return NULL; - } - - global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global); - if (global->ctrl_iface == NULL) { - wpa_supplicant_deinit(global); - return NULL; - } - - if (global->params.dbus_ctrl_interface) { - global->dbus_ctrl_iface = - wpa_supplicant_dbus_ctrl_iface_init(global); - if (global->dbus_ctrl_iface == NULL) { - wpa_supplicant_deinit(global); - return NULL; - } - } - - if (global->params.wait_for_interface && global->params.daemonize && - wpa_supplicant_daemon(global->params.pid_file)) { - wpa_supplicant_deinit(global); - return NULL; - } - - return global; -} - - -/** - * wpa_supplicant_run - Run the %wpa_supplicant main event loop - * @global: Pointer to global data from wpa_supplicant_init() - * Returns: 0 after successful event loop run, -1 on failure - * - * This function starts the main event loop and continues running as long as - * there are any remaining events. In most cases, this function is running as - * long as the %wpa_supplicant process in still in use. - */ -int wpa_supplicant_run(struct wpa_global *global) -{ - struct wpa_supplicant *wpa_s; - - if (!global->params.wait_for_interface && global->params.daemonize && - wpa_supplicant_daemon(global->params.pid_file)) - return -1; - - if (global->params.wait_for_monitor) { - for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) - if (wpa_s->ctrl_iface) - wpa_supplicant_ctrl_iface_wait( - wpa_s->ctrl_iface); - } - - eloop_register_signal_terminate(wpa_supplicant_terminate, NULL); - eloop_register_signal_reconfig(wpa_supplicant_reconfig, NULL); - - eloop_run(); - - return 0; -} - - -/** - * wpa_supplicant_deinit - Deinitialize %wpa_supplicant - * @global: Pointer to global data from wpa_supplicant_init() - * - * This function is called to deinitialize %wpa_supplicant and to free all - * allocated resources. Remaining network interfaces will also be removed. - */ -void wpa_supplicant_deinit(struct wpa_global *global) -{ - if (global == NULL) - return; - - while (global->ifaces) - wpa_supplicant_remove_iface(global, global->ifaces); - - if (global->ctrl_iface) - wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface); - if (global->dbus_ctrl_iface) - wpa_supplicant_dbus_ctrl_iface_deinit(global->dbus_ctrl_iface); - - eap_peer_unregister_methods(); - - eloop_destroy(); - - if (global->params.pid_file) { - os_daemonize_terminate(global->params.pid_file); - os_free(global->params.pid_file); - } - os_free(global->params.ctrl_interface); - - os_free(global); - wpa_debug_close_syslog(); - wpa_debug_close_file(); -} diff --git a/contrib/wpa_supplicant/wpa_supplicant.conf b/contrib/wpa_supplicant/wpa_supplicant.conf deleted file mode 100644 index ec8b0eeb3f21..000000000000 --- a/contrib/wpa_supplicant/wpa_supplicant.conf +++ /dev/null @@ -1,748 +0,0 @@ -##### Example wpa_supplicant configuration file ############################### -# -# This file describes configuration file format and lists all available option. -# Please also take a look at simpler configuration examples in 'examples' -# subdirectory. -# -# Empty lines and lines starting with # are ignored - -# NOTE! This file may contain password information and should probably be made -# readable only by root user on multiuser systems. - -# Note: All file paths in this configuration file should use full (absolute, -# not relative to working directory) path in order to allow working directory -# to be changed. This can happen if wpa_supplicant is run in the background. - -# Whether to allow wpa_supplicant to update (overwrite) configuration -# -# This option can be used to allow wpa_supplicant to overwrite configuration -# file whenever configuration is changed (e.g., new network block is added with -# wpa_cli or wpa_gui, or a password is changed). This is required for -# wpa_cli/wpa_gui to be able to store the configuration changes permanently. -# Please note that overwriting configuration file will remove the comments from -# it. -#update_config=1 - -# global configuration (shared by all network blocks) -# -# Parameters for the control interface. If this is specified, wpa_supplicant -# will open a control interface that is available for external programs to -# manage wpa_supplicant. The meaning of this string depends on which control -# interface mechanism is used. For all cases, the existance of this parameter -# in configuration is used to determine whether the control interface is -# enabled. -# -# For UNIX domain sockets (default on Linux and BSD): This is a directory that -# will be created for UNIX domain sockets 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 -# wpa_supplicant processes can be run at the same time if more than one -# interface is used. -# /var/run/wpa_supplicant is the recommended directory for sockets and by -# default, wpa_cli will use it when trying to connect with wpa_supplicant. -# -# 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 wpa_supplicant 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, wpa_supplicant is configured to use gid 0 (root). If you -# want to allow non-root users to use the control 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. If this variable is commented out or -# not included in the configuration file, group will not be changed from the -# value it got by default when the directory or socket was created. -# -# When configuring both the directory and group, use following format: -# DIR=/var/run/wpa_supplicant GROUP=wheel -# DIR=/var/run/wpa_supplicant GROUP=0 -# (group can be either group name or gid) -# -# For UDP connections (default on Windows): The value will be ignored. This -# variable is just used to select that the control interface is to be created. -# The value can be set to, e.g., udp (ctrl_interface=udp) -# -# For Windows Named Pipe: This value can be used to set the security descriptor -# for controlling access to the control interface. Security descriptor can be -# set using Security Descriptor String Format (see http://msdn.microsoft.com/ -# library/default.asp?url=/library/en-us/secauthz/security/ -# security_descriptor_string_format.asp). The descriptor string needs to be -# prefixed with SDDL=. For example, ctrl_interface=SDDL=D: would set an empty -# DACL (which will reject all connections). See README-Windows.txt for more -# information about SDDL string format. -# -ctrl_interface=/var/run/wpa_supplicant - -# IEEE 802.1X/EAPOL version -# wpa_supplicant is implemented based on IEEE Std 802.1X-2004 which defines -# EAPOL version 2. However, there are many APs that do not handle the new -# version number correctly (they seem to drop the frames completely). In order -# to make wpa_supplicant interoperate with these APs, the version number is set -# to 1 by default. This configuration value can be used to set it to the new -# version (2). -eapol_version=1 - -# AP scanning/selection -# By default, wpa_supplicant requests driver to perform AP scanning and then -# uses the scan results to select a suitable AP. Another alternative is to -# allow the driver to take care of AP scanning and selection and use -# wpa_supplicant just to process EAPOL frames based on IEEE 802.11 association -# information from the driver. -# 1: wpa_supplicant initiates scanning and AP selection -# 0: driver takes care of scanning, AP selection, and IEEE 802.11 association -# parameters (e.g., WPA IE generation); this mode can also be used with -# non-WPA drivers when using IEEE 802.1X mode; do not try to associate with -# APs (i.e., external program needs to control association). This mode must -# also be used when using wired Ethernet drivers. -# 2: like 0, but associate with APs using security policy and SSID (but not -# BSSID); this can be used, e.g., with ndiswrapper and NDIS drivers to -# enable operation with hidden SSIDs and optimized roaming; in this mode, -# the network blocks in the configuration file are tried one by one until -# the driver reports successful association; each network block should have -# explicit security policy (i.e., only one option in the lists) for -# key_mgmt, pairwise, group, proto variables -ap_scan=1 - -# EAP fast re-authentication -# By default, fast re-authentication is enabled for all EAP methods that -# support it. This variable can be used to disable fast re-authentication. -# Normally, there is no need to disable this. -fast_reauth=1 - -# OpenSSL Engine support -# These options can be used to load OpenSSL engines. -# The two engines that are supported currently are shown below: -# They are both from the opensc project (http://www.opensc.org/) -# By default no engines are loaded. -# make the opensc engine available -#opensc_engine_path=/usr/lib/opensc/engine_opensc.so -# make the pkcs11 engine available -#pkcs11_engine_path=/usr/lib/opensc/engine_pkcs11.so -# configure the path to the pkcs11 module required by the pkcs11 engine -#pkcs11_module_path=/usr/lib/pkcs11/opensc-pkcs11.so - -# Dynamic EAP methods -# If EAP methods were built dynamically as shared object files, they need to be -# loaded here before being used in the network blocks. By default, EAP methods -# are included statically in the build, so these lines are not needed -#load_dynamic_eap=/usr/lib/wpa_supplicant/eap_tls.so -#load_dynamic_eap=/usr/lib/wpa_supplicant/eap_md5.so - -# Driver interface parameters -# This field can be used to configure arbitrary driver interace parameters. The -# format is specific to the selected driver interface. This field is not used -# in most cases. -#driver_param="field=value" - -# Maximum lifetime for PMKSA in seconds; default 43200 -#dot11RSNAConfigPMKLifetime=43200 -# Threshold for reauthentication (percentage of PMK lifetime); default 70 -#dot11RSNAConfigPMKReauthThreshold=70 -# Timeout for security association negotiation in seconds; default 60 -#dot11RSNAConfigSATimeout=60 - -# network block -# -# Each network (usually AP's sharing the same SSID) is configured as a separate -# block in this configuration file. The network blocks are in preference order -# (the first match is used). -# -# network block fields: -# -# disabled: -# 0 = this network can be used (default) -# 1 = this network block is disabled (can be enabled through ctrl_iface, -# e.g., with wpa_cli or wpa_gui) -# -# id_str: Network identifier string for external scripts. This value is passed -# to external action script through wpa_cli as WPA_ID_STR environment -# variable to make it easier to do network specific configuration. -# -# ssid: SSID (mandatory); either as an ASCII string with double quotation or -# as hex string; network name -# -# scan_ssid: -# 0 = do not scan this SSID with specific Probe Request frames (default) -# 1 = scan with SSID-specific Probe Request frames (this can be used to -# find APs that do not accept broadcast SSID or use multiple SSIDs; -# this will add latency to scanning, so enable this only when needed) -# -# bssid: BSSID (optional); if set, this network block is used only when -# associating with the AP using the configured BSSID -# -# priority: priority group (integer) -# By default, all networks will get same priority group (0). If some of the -# networks are more desirable, this field can be used to change the order in -# which wpa_supplicant goes through the networks when selecting a BSS. The -# priority groups will be iterated in decreasing priority (i.e., the larger the -# priority value, the sooner the network is matched against the scan results). -# Within each priority group, networks will be selected based on security -# policy, signal strength, etc. -# Please note that AP scanning with scan_ssid=1 and ap_scan=2 mode are not -# using this priority to select the order for scanning. Instead, they try the -# networks in the order that used in the configuration file. -# -# mode: IEEE 802.11 operation mode -# 0 = infrastructure (Managed) mode, i.e., associate with an AP (default) -# 1 = IBSS (ad-hoc, peer-to-peer) -# Note: IBSS can only be used with key_mgmt NONE (plaintext and static WEP) -# and key_mgmt=WPA-NONE (fixed group key TKIP/CCMP). In addition, ap_scan has -# to be set to 2 for IBSS. WPA-None requires following network block options: -# proto=WPA, key_mgmt=WPA-NONE, pairwise=NONE, group=TKIP (or CCMP, but not -# both), and psk must also be set. -# -# frequency: Channel frequency in megahertz (MHz) for IBSS, e.g., -# 2412 = IEEE 802.11b/g channel 1. This value is used to configure the initial -# channel for IBSS (adhoc) networks. It is ignored in the infrastructure mode. -# In addition, this value is only used by the station that creates the IBSS. If -# an IBSS network with the configured SSID is already present, the frequency of -# the network will be used instead of this configured value. -# -# proto: list of accepted protocols -# WPA = WPA/IEEE 802.11i/D3.0 -# RSN = WPA2/IEEE 802.11i (also WPA2 can be used as an alias for RSN) -# If not set, this defaults to: WPA RSN -# -# key_mgmt: list of accepted authenticated key management protocols -# WPA-PSK = WPA pre-shared key (this requires 'psk' field) -# WPA-EAP = WPA using EAP authentication (this can use an external -# program, e.g., Xsupplicant, for IEEE 802.1X EAP Authentication -# IEEE8021X = IEEE 802.1X using EAP authentication and (optionally) dynamically -# generated WEP keys -# NONE = WPA is not used; plaintext or static WEP could be used -# If not set, this defaults to: WPA-PSK WPA-EAP -# -# auth_alg: list of allowed IEEE 802.11 authentication algorithms -# OPEN = Open System authentication (required for WPA/WPA2) -# SHARED = Shared Key authentication (requires static WEP keys) -# LEAP = LEAP/Network EAP (only used with LEAP) -# If not set, automatic selection is used (Open System with LEAP enabled if -# LEAP is allowed as one of the EAP methods). -# -# pairwise: list of accepted pairwise (unicast) ciphers for WPA -# 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] -# NONE = Use only Group Keys (deprecated, should not be included if APs support -# pairwise keys) -# If not set, this defaults to: CCMP TKIP -# -# group: list of accepted group (broadcast/multicast) ciphers for WPA -# 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] -# WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key -# WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key [IEEE 802.11] -# If not set, this defaults to: CCMP TKIP WEP104 WEP40 -# -# psk: WPA preshared key; 256-bit pre-shared key -# The key used in WPA-PSK mode can be entered either as 64 hex-digits, i.e., -# 32 bytes or as an ASCII passphrase (in which case, the real PSK will be -# generated using the passphrase and SSID). ASCII passphrase must be between -# 8 and 63 characters (inclusive). -# This field is not needed, if WPA-EAP is used. -# Note: Separate tool, wpa_passphrase, can be used to generate 256-bit keys -# from ASCII passphrase. This process uses lot of CPU and wpa_supplicant -# startup and reconfiguration time can be optimized by generating the PSK only -# only when the passphrase or SSID has actually changed. -# -# eapol_flags: IEEE 802.1X/EAPOL options (bit field) -# Dynamic WEP key required for non-WPA mode -# bit0 (1): require dynamically generated unicast WEP key -# bit1 (2): require dynamically generated broadcast WEP key -# (3 = require both keys; default) -# Note: When using wired authentication, eapol_flags must be set to 0 for the -# authentication to be completed successfully. -# -# mixed_cell: This option can be used to configure whether so called mixed -# cells, i.e., networks that use both plaintext and encryption in the same -# SSID, are allowed when selecting a BSS form scan results. -# 0 = disabled (default) -# 1 = enabled -# -# proactive_key_caching: -# Enable/disable opportunistic PMKSA caching for WPA2. -# 0 = disabled (default) -# 1 = enabled -# -# wep_key0..3: Static WEP key (ASCII in double quotation, e.g. "abcde" or -# hex without quotation, e.g., 0102030405) -# wep_tx_keyidx: Default WEP key index (TX) (0..3) -# -# peerkey: Whether PeerKey negotiation for direct links (IEEE 802.11e DLS) is -# allowed. This is only used with RSN/WPA2. -# 0 = disabled (default) -# 1 = enabled -#peerkey=1 -# -# Following fields are only used with internal EAP implementation. -# eap: space-separated list of accepted EAP methods -# MD5 = EAP-MD5 (unsecure and does not generate keying material -> -# cannot be used with WPA; to be used as a Phase 2 method -# with EAP-PEAP or EAP-TTLS) -# MSCHAPV2 = EAP-MSCHAPv2 (cannot be used separately with WPA; to be used -# as a Phase 2 method with EAP-PEAP or EAP-TTLS) -# OTP = EAP-OTP (cannot be used separately with WPA; to be used -# as a Phase 2 method with EAP-PEAP or EAP-TTLS) -# GTC = EAP-GTC (cannot be used separately with WPA; to be used -# as a Phase 2 method with EAP-PEAP or EAP-TTLS) -# TLS = EAP-TLS (client and server certificate) -# PEAP = EAP-PEAP (with tunnelled EAP authentication) -# TTLS = EAP-TTLS (with tunnelled EAP or PAP/CHAP/MSCHAP/MSCHAPV2 -# authentication) -# If not set, all compiled in methods are allowed. -# -# identity: Identity string for EAP -# anonymous_identity: Anonymous identity string for EAP (to be used as the -# unencrypted identity with EAP types that support different tunnelled -# identity, e.g., EAP-TTLS) -# password: Password string for EAP -# 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 should be used since working directory may -# change when wpa_supplicant is run in the background. -# 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. -# 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. -# client_cert: File path to client certificate file (PEM/DER) -# Full path 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>. -# 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 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>. -# private_key_passwd: Password for private key file (if left out, this will be -# asked through control interface) -# 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. -# subject_match: Substring to be 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@example.com -# altsubject_match: 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 -# phase1: Phase1 (outer authentication, i.e., TLS tunnel) 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) -# 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) -# Following certificate/private key fields are used in inner Phase2 -# authentication when using EAP-TTLS or EAP-PEAP. -# ca_cert2: File path to CA certificate file. 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. -# ca_path2: Directory path for CA certificate files (PEM) -# client_cert2: File path to client certificate file -# private_key2: File path to client private key file -# private_key2_passwd: Password for private key file -# dh_file2: File path to DH/DSA parameters file (in PEM format) -# subject_match2: Substring to be matched against the subject of the -# authentication server certificate. -# altsubject_match2: Substring to be matched against the alternative subject -# name of the authentication server certificate. -# -# 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. -# -# EAP-PSK variables: -# eappsk: 16-byte (128-bit, 32 hex digits) pre-shared key in hex format -# nai: user NAI -# -# EAP-PAX variables: -# eappsk: 16-byte (128-bit, 32 hex digits) pre-shared key in hex format -# -# EAP-SAKE variables: -# eappsk: 32-byte (256-bit, 64 hex digits) pre-shared key in hex format -# (this is concatenation of Root-Secret-A and Root-Secret-B) -# nai: user NAI (PEERID) -# -# EAP-GPSK variables: -# eappsk: Pre-shared key in hex format (at least 128 bits, i.e., 32 hex digits) -# nai: user NAI (ID_Client) -# -# EAP-FAST variables: -# pac_file: File path for the PAC entries. 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> -# phase1: fast_provisioning=1 option enables in-line provisioning of EAP-FAST -# credentials (PAC) -# -# wpa_supplicant supports number of "EAP workarounds" to work around -# interoperability issues with incorrectly behaving authentication servers. -# These are enabled by default because some of the issues are present in large -# number of authentication servers. Strict EAP conformance mode can be -# configured by disabling workarounds with eap_workaround=0. - -# Example blocks: - -# Simple case: WPA-PSK, PSK as an ASCII passphrase, allow all valid ciphers -network={ - ssid="simple" - psk="very secret passphrase" - priority=5 -} - -# Same as previous, but request SSID-specific scanning (for APs that reject -# broadcast SSID) -network={ - ssid="second ssid" - scan_ssid=1 - psk="very secret passphrase" - priority=2 -} - -# Only WPA-PSK is used. Any valid cipher combination is accepted. -network={ - ssid="example" - proto=WPA - key_mgmt=WPA-PSK - pairwise=CCMP TKIP - group=CCMP TKIP WEP104 WEP40 - psk=06b4be19da289f475aa46a33cb793029d4ab3db7a23ee92382eb0106c72ac7bb - priority=2 -} - -# Only WPA-EAP is used. Both CCMP and TKIP is accepted. An AP that used WEP104 -# or WEP40 as the group cipher will not be accepted. -network={ - ssid="example" - proto=RSN - key_mgmt=WPA-EAP - pairwise=CCMP TKIP - group=CCMP TKIP - eap=TLS - identity="user@example.com" - ca_cert="/etc/cert/ca.pem" - client_cert="/etc/cert/user.pem" - private_key="/etc/cert/user.prv" - private_key_passwd="password" - priority=1 -} - -# EAP-PEAP/MSCHAPv2 configuration for RADIUS servers that use the new peaplabel -# (e.g., Radiator) -network={ - ssid="example" - key_mgmt=WPA-EAP - eap=PEAP - identity="user@example.com" - password="foobar" - ca_cert="/etc/cert/ca.pem" - phase1="peaplabel=1" - phase2="auth=MSCHAPV2" - priority=10 -} - -# EAP-TTLS/EAP-MD5-Challenge configuration with anonymous identity for the -# unencrypted use. Real identity is sent only within an encrypted TLS tunnel. -network={ - ssid="example" - key_mgmt=WPA-EAP - eap=TTLS - identity="user@example.com" - anonymous_identity="anonymous@example.com" - password="foobar" - ca_cert="/etc/cert/ca.pem" - priority=2 -} - -# EAP-TTLS/MSCHAPv2 configuration with anonymous identity for the unencrypted -# use. Real identity is sent only within an encrypted TLS tunnel. -network={ - ssid="example" - key_mgmt=WPA-EAP - eap=TTLS - identity="user@example.com" - anonymous_identity="anonymous@example.com" - password="foobar" - ca_cert="/etc/cert/ca.pem" - phase2="auth=MSCHAPV2" -} - -# WPA-EAP, EAP-TTLS with different CA certificate used for outer and inner -# authentication. -network={ - ssid="example" - key_mgmt=WPA-EAP - eap=TTLS - # Phase1 / outer authentication - anonymous_identity="anonymous@example.com" - ca_cert="/etc/cert/ca.pem" - # Phase 2 / inner authentication - phase2="autheap=TLS" - ca_cert2="/etc/cert/ca2.pem" - client_cert2="/etc/cer/user.pem" - private_key2="/etc/cer/user.prv" - private_key2_passwd="password" - priority=2 -} - -# Both WPA-PSK and WPA-EAP is accepted. Only CCMP is accepted as pairwise and -# group cipher. -network={ - ssid="example" - bssid=00:11:22:33:44:55 - proto=WPA RSN - key_mgmt=WPA-PSK WPA-EAP - pairwise=CCMP - group=CCMP - psk=06b4be19da289f475aa46a33cb793029d4ab3db7a23ee92382eb0106c72ac7bb -} - -# Special characters in SSID, so use hex string. Default to WPA-PSK, WPA-EAP -# and all valid ciphers. -network={ - ssid=00010203 - psk=000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f -} - - -# EAP-SIM with a GSM SIM or USIM -network={ - ssid="eap-sim-test" - key_mgmt=WPA-EAP - eap=SIM - pin="1234" - pcsc="" -} - - -# EAP-PSK -network={ - ssid="eap-psk-test" - key_mgmt=WPA-EAP - eap=PSK - identity="eap_psk_user" - eappsk=06b4be19da289f475aa46a33cb793029 - nai="eap_psk_user@example.com" -} - - -# IEEE 802.1X/EAPOL with dynamically generated WEP keys (i.e., no WPA) using -# EAP-TLS for authentication and key generation; require both unicast and -# broadcast WEP keys. -network={ - ssid="1x-test" - key_mgmt=IEEE8021X - eap=TLS - identity="user@example.com" - ca_cert="/etc/cert/ca.pem" - client_cert="/etc/cert/user.pem" - private_key="/etc/cert/user.prv" - private_key_passwd="password" - eapol_flags=3 -} - - -# LEAP with dynamic WEP keys -network={ - ssid="leap-example" - key_mgmt=IEEE8021X - eap=LEAP - identity="user" - password="foobar" -} - -# EAP-FAST with WPA (WPA or WPA2) -network={ - ssid="eap-fast-test" - key_mgmt=WPA-EAP - eap=FAST - anonymous_identity="FAST-000102030405" - identity="username" - password="password" - phase1="fast_provisioning=1" - pac_file="/etc/wpa_supplicant.eap-fast-pac" -} - -network={ - ssid="eap-fast-test" - key_mgmt=WPA-EAP - eap=FAST - anonymous_identity="FAST-000102030405" - identity="username" - password="password" - phase1="fast_provisioning=1" - pac_file="blob://eap-fast-pac" -} - -# Plaintext connection (no WPA, no IEEE 802.1X) -network={ - ssid="plaintext-test" - key_mgmt=NONE -} - - -# Shared WEP key connection (no WPA, no IEEE 802.1X) -network={ - ssid="static-wep-test" - key_mgmt=NONE - wep_key0="abcde" - wep_key1=0102030405 - wep_key2="1234567890123" - wep_tx_keyidx=0 - priority=5 -} - - -# Shared WEP key connection (no WPA, no IEEE 802.1X) using Shared Key -# IEEE 802.11 authentication -network={ - ssid="static-wep-test2" - key_mgmt=NONE - wep_key0="abcde" - wep_key1=0102030405 - wep_key2="1234567890123" - wep_tx_keyidx=0 - priority=5 - auth_alg=SHARED -} - - -# IBSS/ad-hoc network with WPA-None/TKIP. -network={ - ssid="test adhoc" - mode=1 - frequency=2412 - proto=WPA - key_mgmt=WPA-NONE - pairwise=NONE - group=TKIP - psk="secret passphrase" -} - - -# Catch all example that allows more or less all configuration modes -network={ - ssid="example" - scan_ssid=1 - key_mgmt=WPA-EAP WPA-PSK IEEE8021X NONE - pairwise=CCMP TKIP - group=CCMP TKIP WEP104 WEP40 - psk="very secret passphrase" - eap=TTLS PEAP TLS - identity="user@example.com" - password="foobar" - ca_cert="/etc/cert/ca.pem" - client_cert="/etc/cert/user.pem" - private_key="/etc/cert/user.prv" - private_key_passwd="password" - phase1="peaplabel=0" -} - -# Example of EAP-TLS with smartcard (openssl engine) -network={ - ssid="example" - key_mgmt=WPA-EAP - eap=TLS - proto=RSN - pairwise=CCMP TKIP - group=CCMP TKIP - identity="user@example.com" - ca_cert="/etc/cert/ca.pem" - client_cert="/etc/cert/user.pem" - - engine=1 - - # The engine configured here must be available. Look at - # OpenSSL engine support in the global section. - # The key available through the engine must be the private key - # matching the client certificate configured above. - - # use the opensc engine - #engine_id="opensc" - #key_id="45" - - # use the pkcs11 engine - engine_id="pkcs11" - key_id="id_45" - - # Optional PIN configuration; this can be left out and PIN will be - # asked through the control interface - pin="1234" -} - -# Example configuration showing how to use an inlined blob as a CA certificate -# data instead of using external file -network={ - ssid="example" - key_mgmt=WPA-EAP - eap=TTLS - identity="user@example.com" - anonymous_identity="anonymous@example.com" - password="foobar" - ca_cert="blob://exampleblob" - priority=20 -} - -blob-base64-exampleblob={ -SGVsbG8gV29ybGQhCg== -} - - -# Wildcard match for SSID (plaintext APs only). This example select any -# open AP regardless of its SSID. -network={ - key_mgmt=NONE -} diff --git a/contrib/wpa_supplicant/wpa_supplicant.h b/contrib/wpa_supplicant/wpa_supplicant.h deleted file mode 100644 index 763f30d2add3..000000000000 --- a/contrib/wpa_supplicant/wpa_supplicant.h +++ /dev/null @@ -1,273 +0,0 @@ -/* - * wpa_supplicant - Exported functions for wpa_supplicant modules - * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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_SUPPLICANT_H -#define WPA_SUPPLICANT_H - -/* Driver wrappers are not supposed to directly touch the internal data - * structure used in wpa_supplicant, so that definition is not provided here. - */ -struct wpa_supplicant; - -/** - * enum wpa_event_type - Event type for wpa_supplicant_event() calls - */ -typedef 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 even 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. - */ - 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 is 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. - */ - 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 -} wpa_event_type; - - -/** - * 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 { - /** - * 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). - */ - 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). - */ - 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). - */ - u8 *beacon_ies; - - /** - * beacon_ies_len - Length of beacon_ies */ - size_t beacon_ies_len; - } assoc_info; - - /** - * struct michael_mic_failure - Data for EVENT_MICHAEL_MIC_FAILURE - */ - struct michael_mic_failure { - int unicast; - } 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; -}; - -/** - * wpa_supplicant_event - Report a driver event for wpa_supplicant - * @wpa_s: pointer to wpa_supplicant data; 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(struct wpa_supplicant *wpa_s, wpa_event_type event, - union wpa_event_data *data); - -/** - * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant - * @ctx: Context pointer (wpa_s) - * @src_addr: Source address of the EAPOL frame - * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header) - * @len: Length of the EAPOL data - * - * This function is called for each received EAPOL frame. - */ -void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr, - const u8 *buf, size_t len); - -#endif /* WPA_SUPPLICANT_H */ diff --git a/contrib/wpa_supplicant/wpa_supplicant_i.h b/contrib/wpa_supplicant/wpa_supplicant_i.h deleted file mode 100644 index 95d171c0a23f..000000000000 --- a/contrib/wpa_supplicant/wpa_supplicant_i.h +++ /dev/null @@ -1,701 +0,0 @@ -/* - * wpa_supplicant - Internal definitions - * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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_SUPPLICANT_I_H -#define WPA_SUPPLICANT_I_H - -#include "driver.h" - -struct wpa_blacklist { - struct wpa_blacklist *next; - u8 bssid[ETH_ALEN]; - int count; -}; - - -struct wpa_scan_result; -struct wpa_sm; -struct wpa_supplicant; - -/* - * Forward declarations of private structures used within the ctrl_iface - * backends. Other parts of wpa_supplicant do not have access to data stored in - * these structures. - */ -struct ctrl_iface_priv; -struct ctrl_iface_global_priv; -struct ctrl_iface_dbus_priv; - -/** - * struct wpa_interface - Parameters for wpa_supplicant_add_iface() - */ -struct wpa_interface { - /** - * confname - Configuration name (file or profile) name - * - * This can also be %NULL when a configuration file is not used. In - * that case, ctrl_interface must be set to allow the interface to be - * configured. - */ - const char *confname; - - /** - * ctrl_interface - Control interface parameter - * - * If a configuration file is not used, this variable can be used to - * set the ctrl_interface parameter that would have otherwise been read - * from the configuration file. If both confname and ctrl_interface are - * set, ctrl_interface is used to override the value from configuration - * file. - */ - const char *ctrl_interface; - - /** - * driver - Driver interface name, or %NULL to use the default driver - */ - const char *driver; - - /** - * driver_param - Driver interface parameters - * - * If a configuration file is not used, this variable can be used to - * set the driver_param parameters that would have otherwise been read - * from the configuration file. If both confname and driver_param are - * set, driver_param is used to override the value from configuration - * file. - */ - const char *driver_param; - - /** - * ifname - Interface name - */ - const char *ifname; - - /** - * bridge_ifname - Optional bridge interface name - * - * If the driver interface (ifname) is included in a Linux bridge - * device, the bridge interface may need to be used for receiving EAPOL - * frames. This can be enabled by setting this variable to enable - * receiving of EAPOL frames from an additional interface. - */ - const char *bridge_ifname; -}; - -/** - * struct wpa_params - Parameters for wpa_supplicant_init() - */ -struct wpa_params { - /** - * daemonize - Run %wpa_supplicant in the background - */ - int daemonize; - - /** - * wait_for_interface - Wait for the network interface to appear - * - * If set, %wpa_supplicant will wait until all the configured network - * interfaces are available before starting processing. Please note - * that in many cases, a better alternative would be to start - * %wpa_supplicant without network interfaces and add the interfaces - * dynamically whenever they become available. - */ - int wait_for_interface; - - /** - * wait_for_monitor - Wait for a monitor program before starting - */ - int wait_for_monitor; - - /** - * pid_file - Path to a PID (process ID) file - * - * If this and daemonize are set, process ID of the background process - * will be written to the specified file. - */ - char *pid_file; - - /** - * wpa_debug_level - Debugging verbosity level (e.g., MSG_INFO) - */ - int wpa_debug_level; - - /** - * wpa_debug_show_keys - Whether keying material is included in debug - * - * This parameter can be used to allow keying material to be included - * in debug messages. This is a security risk and this option should - * not be enabled in normal configuration. If needed during - * development or while troubleshooting, this option can provide more - * details for figuring out what is happening. - */ - int wpa_debug_show_keys; - - /** - * wpa_debug_timestamp - Whether to include timestamp in debug messages - */ - int wpa_debug_timestamp; - - /** - * ctrl_interface - Global ctrl_iface path/parameter - */ - char *ctrl_interface; - - /** - * dbus_ctrl_interface - Enable the DBus control interface - */ - int dbus_ctrl_interface; - - /** - * wpa_debug_file_path - Path of debug file or %NULL to use stdout - */ - const char *wpa_debug_file_path; - - /** - * wpa_debug_syslog - Enable log output through syslog - */ - const char *wpa_debug_syslog; -}; - -/** - * struct wpa_global - Internal, global data for all %wpa_supplicant interfaces - * - * This structure is initialized by calling wpa_supplicant_init() when starting - * %wpa_supplicant. - */ -struct wpa_global { - struct wpa_supplicant *ifaces; - struct wpa_params params; - struct ctrl_iface_global_priv *ctrl_iface; - struct ctrl_iface_dbus_priv *dbus_ctrl_iface; -}; - - -struct wpa_client_mlme { -#ifdef CONFIG_CLIENT_MLME - enum { - IEEE80211_DISABLED, IEEE80211_AUTHENTICATE, - IEEE80211_ASSOCIATE, IEEE80211_ASSOCIATED, - IEEE80211_IBSS_SEARCH, IEEE80211_IBSS_JOINED - } state; - u8 prev_bssid[ETH_ALEN]; - u8 ssid[32]; - size_t ssid_len; - u16 aid; - u16 ap_capab, capab; - u8 *extra_ie; /* to be added to the end of AssocReq */ - size_t extra_ie_len; - wpa_key_mgmt key_mgmt; - - /* The last AssocReq/Resp IEs */ - u8 *assocreq_ies, *assocresp_ies; - size_t assocreq_ies_len, assocresp_ies_len; - - int auth_tries, assoc_tries; - - unsigned int ssid_set:1; - unsigned int bssid_set:1; - unsigned int prev_bssid_set:1; - unsigned int authenticated:1; - unsigned int associated:1; - unsigned int probereq_poll:1; - unsigned int use_protection:1; - unsigned int create_ibss:1; - unsigned int mixed_cell:1; - unsigned int wmm_enabled:1; - - struct os_time last_probe; - -#define IEEE80211_AUTH_ALG_OPEN BIT(0) -#define IEEE80211_AUTH_ALG_SHARED_KEY BIT(1) -#define IEEE80211_AUTH_ALG_LEAP BIT(2) - unsigned int auth_algs; /* bitfield of allowed auth algs */ - int auth_alg; /* currently used IEEE 802.11 authentication algorithm */ - int auth_transaction; - - struct os_time ibss_join_req; - u8 *probe_resp; /* ProbeResp template for IBSS */ - size_t probe_resp_len; - u32 supp_rates_bits; - - int wmm_last_param_set; - - int sta_scanning; - int scan_hw_mode_idx; - int scan_channel_idx; - enum { SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state; - struct os_time last_scan_completed; - int scan_oper_channel; - int scan_oper_freq; - int scan_oper_phymode; - u8 scan_ssid[32]; - size_t scan_ssid_len; - int scan_skip_11b; - - struct ieee80211_sta_bss *sta_bss_list; -#define STA_HASH_SIZE 256 -#define STA_HASH(sta) (sta[5]) - struct ieee80211_sta_bss *sta_bss_hash[STA_HASH_SIZE]; - - int cts_protect_erp_frames; - - int phymode; /* current mode; WPA_MODE_IEEE80211A, .. */ - struct wpa_hw_modes *modes; - size_t num_modes; - unsigned int hw_modes; /* bitfield of allowed hardware modes; - * (1 << MODE_*) */ - int num_curr_rates; - struct wpa_rate_data *curr_rates; - int freq; /* The current frequency in MHz */ - int channel; /* The current IEEE 802.11 channel number */ -#else /* CONFIG_CLIENT_MLME */ - int dummy; /* to keep MSVC happy */ -#endif /* CONFIG_CLIENT_MLME */ -}; - -/** - * struct wpa_supplicant - Internal data for wpa_supplicant interface - * - * This structure contains the internal data for core wpa_supplicant code. This - * should be only used directly from the core code. However, a pointer to this - * data is used from other files as an arbitrary context pointer in calls to - * core functions. - */ -struct wpa_supplicant { - struct wpa_global *global; - struct wpa_supplicant *next; - struct l2_packet_data *l2; - struct l2_packet_data *l2_br; - unsigned char own_addr[ETH_ALEN]; - char ifname[100]; -#ifdef CONFIG_CTRL_IFACE_DBUS - char *dbus_path; -#endif /* CONFIG_CTRL_IFACE_DBUS */ - char bridge_ifname[16]; - - char *confname; - struct wpa_config *conf; - int countermeasures; - os_time_t last_michael_mic_error; - u8 bssid[ETH_ALEN]; - u8 pending_bssid[ETH_ALEN]; /* If wpa_state == WPA_ASSOCIATING, this - * field contains the targer BSSID. */ - int reassociate; /* reassociation requested */ - int disconnected; /* all connections disabled; i.e., do no reassociate - * before this has been cleared */ - struct wpa_ssid *current_ssid; - - /* Selected configuration (based on Beacon/ProbeResp WPA IE) */ - int pairwise_cipher; - int group_cipher; - int key_mgmt; - int mgmt_group_cipher; - - void *drv_priv; /* private data used by driver_ops */ - - struct wpa_ssid *prev_scan_ssid; /* previously scanned SSID; - * NULL = not yet initialized (start - * with broadcast SSID) - * BROADCAST_SSID_SCAN = broadcast - * SSID was used in the previous scan - */ -#define BROADCAST_SSID_SCAN ((struct wpa_ssid *) 1) - - struct wpa_scan_result *scan_results; - int num_scan_results; - - struct wpa_driver_ops *driver; - int interface_removed; /* whether the network interface has been - * removed */ - struct wpa_sm *wpa; - struct eapol_sm *eapol; - - struct ctrl_iface_priv *ctrl_iface; - - wpa_states wpa_state; - int new_connection; - int reassociated_connection; - - int eapol_received; /* number of EAPOL packets received after the - * previous association event */ - - struct scard_data *scard; - - unsigned char last_eapol_src[ETH_ALEN]; - - int keys_cleared; - - struct wpa_blacklist *blacklist; - - int scan_req; /* manual scan request; this forces a scan even if there - * are no enabled networks in the configuration */ - int scan_res_tried; /* whether ap_scan=1 mode has tried to fetch scan - * results without a new scan request; this is used - * to speed up the first association if the driver - * has already available scan results. */ - - struct wpa_client_mlme mlme; - int use_client_mlme; -}; - - -/* wpa_supplicant.c */ -void wpa_supplicant_cancel_scan(struct wpa_supplicant *wpa_s); - -int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s); - -const char * wpa_supplicant_state_txt(int state); -int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s, - int wait_for_interface); -struct wpa_blacklist * wpa_blacklist_get(struct wpa_supplicant *wpa_s, - const u8 *bssid); -int wpa_blacklist_add(struct wpa_supplicant *wpa_s, const u8 *bssid); -void wpa_blacklist_clear(struct wpa_supplicant *wpa_s); -int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, - struct wpa_scan_result *bss, - struct wpa_ssid *ssid, - u8 *wpa_ie, size_t *wpa_ie_len); -void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, - struct wpa_scan_result *bss, - struct wpa_ssid *ssid); -void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s, - struct wpa_ssid *ssid); -void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s); -int wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s); -void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr); -void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s, - int sec, int usec); -void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, wpa_states state); -struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s); -void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s); -void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s, - int reason_code); -void wpa_supplicant_disassociate(struct wpa_supplicant *wpa_s, - int reason_code); -void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec); - -void wpa_show_license(void); - -struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global, - struct wpa_interface *iface); -int wpa_supplicant_remove_iface(struct wpa_global *global, - struct wpa_supplicant *wpa_s); -struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global, - const char *ifname); -struct wpa_global * wpa_supplicant_init(struct wpa_params *params); -int wpa_supplicant_run(struct wpa_global *global); -void wpa_supplicant_deinit(struct wpa_global *global); - -int wpa_supplicant_scard_init(struct wpa_supplicant *wpa_s, - struct wpa_ssid *ssid); - -/* events.c */ -void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s); - -/* driver_ops */ -static inline void * wpa_drv_init(struct wpa_supplicant *wpa_s, - const char *ifname) -{ - if (wpa_s->driver->init) { - return wpa_s->driver->init(wpa_s, ifname); - } - return NULL; -} - -static inline void wpa_drv_deinit(struct wpa_supplicant *wpa_s) -{ - if (wpa_s->driver->deinit) - wpa_s->driver->deinit(wpa_s->drv_priv); -} - -static inline int wpa_drv_set_param(struct wpa_supplicant *wpa_s, - const char *param) -{ - if (wpa_s->driver->set_param) - return wpa_s->driver->set_param(wpa_s->drv_priv, param); - return 0; -} - -static inline int wpa_drv_set_drop_unencrypted(struct wpa_supplicant *wpa_s, - int enabled) -{ - if (wpa_s->driver->set_drop_unencrypted) { - return wpa_s->driver->set_drop_unencrypted(wpa_s->drv_priv, - enabled); - } - return -1; -} - -static inline int wpa_drv_set_countermeasures(struct wpa_supplicant *wpa_s, - int enabled) -{ - if (wpa_s->driver->set_countermeasures) { - return wpa_s->driver->set_countermeasures(wpa_s->drv_priv, - enabled); - } - return -1; -} - -static inline int wpa_drv_set_auth_alg(struct wpa_supplicant *wpa_s, - int auth_alg) -{ - if (wpa_s->driver->set_auth_alg) { - return wpa_s->driver->set_auth_alg(wpa_s->drv_priv, - auth_alg); - } - return -1; -} - -static inline int wpa_drv_set_wpa(struct wpa_supplicant *wpa_s, int enabled) -{ - if (wpa_s->driver->set_wpa) { - return wpa_s->driver->set_wpa(wpa_s->drv_priv, enabled); - } - return 0; -} - -static inline int wpa_drv_associate(struct wpa_supplicant *wpa_s, - struct wpa_driver_associate_params *params) -{ - if (wpa_s->driver->associate) { - return wpa_s->driver->associate(wpa_s->drv_priv, params); - } - return -1; -} - -static inline int wpa_drv_scan(struct wpa_supplicant *wpa_s, const u8 *ssid, - size_t ssid_len) -{ - if (wpa_s->driver->scan) { - return wpa_s->driver->scan(wpa_s->drv_priv, ssid, ssid_len); - } - return -1; -} - -static inline int wpa_drv_get_scan_results(struct wpa_supplicant *wpa_s, - struct wpa_scan_result *results, - size_t max_size) -{ - if (wpa_s->driver->get_scan_results) { - return wpa_s->driver->get_scan_results(wpa_s->drv_priv, - results, max_size); - } - return -1; -} - -static inline int wpa_drv_get_bssid(struct wpa_supplicant *wpa_s, u8 *bssid) -{ - if (wpa_s->driver->get_bssid) { - return wpa_s->driver->get_bssid(wpa_s->drv_priv, bssid); - } - return -1; -} - -static inline int wpa_drv_get_ssid(struct wpa_supplicant *wpa_s, u8 *ssid) -{ - if (wpa_s->driver->get_ssid) { - return wpa_s->driver->get_ssid(wpa_s->drv_priv, ssid); - } - return -1; -} - -static inline int wpa_drv_set_key(struct wpa_supplicant *wpa_s, 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 (wpa_s->driver->set_key) { - wpa_s->keys_cleared = 0; - return wpa_s->driver->set_key(wpa_s->drv_priv, alg, addr, - key_idx, set_tx, seq, seq_len, - key, key_len); - } - return -1; -} - -static inline int wpa_drv_deauthenticate(struct wpa_supplicant *wpa_s, - const u8 *addr, int reason_code) -{ - if (wpa_s->driver->deauthenticate) { - return wpa_s->driver->deauthenticate(wpa_s->drv_priv, addr, - reason_code); - } - return -1; -} - -static inline int wpa_drv_disassociate(struct wpa_supplicant *wpa_s, - const u8 *addr, int reason_code) -{ - if (wpa_s->driver->disassociate) { - return wpa_s->driver->disassociate(wpa_s->drv_priv, addr, - reason_code); - } - return -1; -} - -static inline int wpa_drv_add_pmkid(struct wpa_supplicant *wpa_s, - const u8 *bssid, const u8 *pmkid) -{ - if (wpa_s->driver->add_pmkid) { - return wpa_s->driver->add_pmkid(wpa_s->drv_priv, bssid, pmkid); - } - return -1; -} - -static inline int wpa_drv_remove_pmkid(struct wpa_supplicant *wpa_s, - const u8 *bssid, const u8 *pmkid) -{ - if (wpa_s->driver->remove_pmkid) { - return wpa_s->driver->remove_pmkid(wpa_s->drv_priv, bssid, - pmkid); - } - return -1; -} - -static inline int wpa_drv_flush_pmkid(struct wpa_supplicant *wpa_s) -{ - if (wpa_s->driver->flush_pmkid) { - return wpa_s->driver->flush_pmkid(wpa_s->drv_priv); - } - return -1; -} - -static inline int wpa_drv_get_capa(struct wpa_supplicant *wpa_s, - struct wpa_driver_capa *capa) -{ - if (wpa_s->driver->get_capa) { - return wpa_s->driver->get_capa(wpa_s->drv_priv, capa); - } - return -1; -} - -static inline void wpa_drv_poll(struct wpa_supplicant *wpa_s) -{ - if (wpa_s->driver->poll) { - wpa_s->driver->poll(wpa_s->drv_priv); - } -} - -static inline const char * wpa_drv_get_ifname(struct wpa_supplicant *wpa_s) -{ - if (wpa_s->driver->get_ifname) { - return wpa_s->driver->get_ifname(wpa_s->drv_priv); - } - return NULL; -} - -static inline const u8 * wpa_drv_get_mac_addr(struct wpa_supplicant *wpa_s) -{ - if (wpa_s->driver->get_mac_addr) { - return wpa_s->driver->get_mac_addr(wpa_s->drv_priv); - } - return NULL; -} - -static inline int wpa_drv_send_eapol(struct wpa_supplicant *wpa_s, - const u8 *dst, u16 proto, - const u8 *data, size_t data_len) -{ - if (wpa_s->driver->send_eapol) - return wpa_s->driver->send_eapol(wpa_s->drv_priv, dst, proto, - data, data_len); - return -1; -} - -static inline int wpa_drv_set_operstate(struct wpa_supplicant *wpa_s, - int state) -{ - if (wpa_s->driver->set_operstate) - return wpa_s->driver->set_operstate(wpa_s->drv_priv, state); - return 0; -} - -static inline int wpa_drv_mlme_setprotection(struct wpa_supplicant *wpa_s, - const u8 *addr, int protect_type, - int key_type) -{ - if (wpa_s->driver->mlme_setprotection) - return wpa_s->driver->mlme_setprotection(wpa_s->drv_priv, addr, - protect_type, - key_type); - return 0; -} - -static inline struct wpa_hw_modes * -wpa_drv_get_hw_feature_data(struct wpa_supplicant *wpa_s, u16 *num_modes, - u16 *flags) -{ - if (wpa_s->driver->get_hw_feature_data) - return wpa_s->driver->get_hw_feature_data(wpa_s->drv_priv, - num_modes, flags); - return NULL; -} - -static inline int wpa_drv_set_channel(struct wpa_supplicant *wpa_s, - wpa_hw_mode phymode, int chan, - int freq) -{ - if (wpa_s->driver->set_channel) - return wpa_s->driver->set_channel(wpa_s->drv_priv, phymode, - chan, freq); - return -1; -} - -static inline int wpa_drv_set_ssid(struct wpa_supplicant *wpa_s, - const u8 *ssid, size_t ssid_len) -{ - if (wpa_s->driver->set_ssid) { - return wpa_s->driver->set_ssid(wpa_s->drv_priv, ssid, - ssid_len); - } - return -1; -} - -static inline int wpa_drv_set_bssid(struct wpa_supplicant *wpa_s, - const u8 *bssid) -{ - if (wpa_s->driver->set_bssid) { - return wpa_s->driver->set_bssid(wpa_s->drv_priv, bssid); - } - return -1; -} - -static inline int wpa_drv_send_mlme(struct wpa_supplicant *wpa_s, - const u8 *data, size_t data_len) -{ - if (wpa_s->driver->send_mlme) - return wpa_s->driver->send_mlme(wpa_s->drv_priv, - data, data_len); - return -1; -} - -static inline int wpa_drv_mlme_add_sta(struct wpa_supplicant *wpa_s, - const u8 *addr, const u8 *supp_rates, - size_t supp_rates_len) -{ - if (wpa_s->driver->mlme_add_sta) - return wpa_s->driver->mlme_add_sta(wpa_s->drv_priv, addr, - supp_rates, supp_rates_len); - return -1; -} - -static inline int wpa_drv_mlme_remove_sta(struct wpa_supplicant *wpa_s, - const u8 *addr) -{ - if (wpa_s->driver->mlme_remove_sta) - return wpa_s->driver->mlme_remove_sta(wpa_s->drv_priv, addr); - return -1; -} - -#endif /* WPA_SUPPLICANT_I_H */ diff --git a/contrib/wpa_supplicant/x509v3.c b/contrib/wpa_supplicant/x509v3.c deleted file mode 100644 index 484c54bad897..000000000000 --- a/contrib/wpa_supplicant/x509v3.c +++ /dev/null @@ -1,1676 +0,0 @@ -/* - * X.509v3 certificate parsing and processing (RFC 3280 profile) - * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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_INTERNAL_X509 - -#include "asn1.h" -#include "crypto.h" -#include "x509v3.h" - - -static void x509_free_name(struct x509_name *name) -{ - os_free(name->cn); - os_free(name->c); - os_free(name->l); - os_free(name->st); - os_free(name->o); - os_free(name->ou); - os_free(name->email); - name->cn = name->c = name->l = name->st = name->o = name->ou = NULL; - name->email = NULL; -} - - -/** - * 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; - - if (!a && b) - return -1; - if (a && !b) - return 1; - if (!a && !b) - return 0; - - res = x509_str_compare(a->cn, b->cn); - if (res) - return res; - res = x509_str_compare(a->c, b->c); - if (res) - return res; - res = x509_str_compare(a->l, b->l); - if (res) - return res; - res = x509_str_compare(a->st, b->st); - if (res) - return res; - res = x509_str_compare(a->o, b->o); - if (res) - return res; - res = x509_str_compare(a->ou, b->ou); - 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 **fieldp; - - /* - * 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) { - 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). - */ - fieldp = NULL; - 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 */ - fieldp = &name->cn; - break; - case 6: - /* countryName */ - fieldp = &name->c; - break; - case 7: - /* localityName */ - fieldp = &name->l; - break; - case 8: - /* stateOrProvinceName */ - fieldp = &name->st; - break; - case 10: - /* organizationName */ - fieldp = &name->o; - break; - case 11: - /* organizationalUnitName */ - fieldp = &name->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 */ - fieldp = &name->email; - } - - if (fieldp == NULL) { - 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; - } - - os_free(*fieldp); - *fieldp = os_malloc(hdr.length + 1); - if (*fieldp == NULL) { - x509_free_name(name); - return -1; - } - os_memcpy(*fieldp, hdr.payload, hdr.length); - (*fieldp)[hdr.length] = '\0'; - } - - return 0; -} - - -/** - * 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; - - if (len == 0) - return; - - pos = buf; - end = buf + len; - - if (name->c) { - ret = os_snprintf(pos, end - pos, "C=%s, ", name->c); - if (ret < 0 || ret >= end - pos) - goto done; - pos += ret; - } - if (name->st) { - ret = os_snprintf(pos, end - pos, "ST=%s, ", name->st); - if (ret < 0 || ret >= end - pos) - goto done; - pos += ret; - } - if (name->l) { - ret = os_snprintf(pos, end - pos, "L=%s, ", name->l); - if (ret < 0 || ret >= end - pos) - goto done; - pos += ret; - } - if (name->o) { - ret = os_snprintf(pos, end - pos, "O=%s, ", name->o); - if (ret < 0 || ret >= end - pos) - goto done; - pos += ret; - } - if (name->ou) { - ret = os_snprintf(pos, end - pos, "OU=%s, ", name->ou); - if (ret < 0 || ret >= end - pos) - goto done; - pos += ret; - } - if (name->cn) { - ret = os_snprintf(pos, end - pos, "CN=%s, ", name->cn); - if (ret < 0 || ret >= end - pos) - goto done; - pos += ret; - } - - if (pos > buf + 1 && pos[-1] == ' ' && pos[-2] == ',') { - *pos-- = '\0'; - *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_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) - * the subject alternative name (section 4.2.1.7) - * 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 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 */; -} - - -/** - * 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[20]; - 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_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 2: /* md2WithRSAEncryption */ - case 11: /* sha256WithRSAEncryption */ - 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"); - *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; -} - -#endif /* CONFIG_INTERNAL_X509 */ diff --git a/contrib/wpa_supplicant/x509v3.h b/contrib/wpa_supplicant/x509v3.h deleted file mode 100644 index a52bcf886453..000000000000 --- a/contrib/wpa_supplicant/x509v3.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * X.509v3 certificate parsing and processing - * Copyright (c) 2006, Jouni Malinen <j@w1.fi> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published 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 { - char *cn; /* commonName */ - char *c; /* countryName */ - char *l; /* localityName */ - char *st; /* stateOrProvinceName */ - char *o; /* organizationName */ - char *ou; /* organizationalUnitName */ - char *email; /* emailAddress */ -}; - -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) - - /* 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 -}; - -#ifdef CONFIG_INTERNAL_X509 - -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); - -#else /* CONFIG_INTERNAL_X509 */ - -static inline void x509_certificate_free(struct x509_certificate *cert) -{ -} - -static inline struct x509_certificate * -x509_certificate_parse(const u8 *buf, size_t len) -{ - return NULL; -} - -static inline void x509_name_string(struct x509_name *name, char *buf, - size_t len) -{ - if (len) - buf[0] = '\0'; -} - -static inline void x509_certificate_chain_free(struct x509_certificate *cert) -{ -} - -static inline int -x509_certificate_chain_validate(struct x509_certificate *trusted, - struct x509_certificate *chain, - int *reason) -{ - return -1; -} - -static inline struct x509_certificate * -x509_certificate_get_subject(struct x509_certificate *chain, - struct x509_name *name) -{ - return NULL; -} - -static inline int x509_certificate_self_signed(struct x509_certificate *cert) -{ - return -1; -} - -#endif /* CONFIG_INTERNAL_X509 */ - -#endif /* X509V3_H */ |