pax_global_header00006660000000000000000000000064122303651710014512gustar00rootroot0000000000000052 comment=686cb9bf858598a640811cd28c52226070258e1c ike-2.2.1+dfsg/000077500000000000000000000000001223036517100132035ustar00rootroot00000000000000ike-2.2.1+dfsg/.gitignore000066400000000000000000000007301223036517100151730ustar00rootroot00000000000000# CMake # ################## CMakeCache.txt CMakeFiles/ Makefile cmake_install.cmake # Compiled or generated source # ################################ source/iked/conf.parse.cpp source/iked/conf.parse.hpp source/iked/conf.token.cpp source/iked/location.hh source/iked/position.hh source/iked/stack.hh source/ikec/ikec source/iked/iked source/qikea/qikea source/qikec/qikec lib*.so* # Qt # ###### *.qrc.depends moc_*.cxx qrc_*.cxx ui_*.h # Misc # ######## *~ .DS_Store ike-2.2.1+dfsg/CMakeLists.txt000066400000000000000000000201021223036517100157360ustar00rootroot00000000000000# # Shrew Soft VPN / IKE Tools # Cross Platform Make File # # author : Matthew Grooms # : mgrooms@shrew.net # : Copyright 2012, Shrew Soft Inc # project( IKE ) cmake_minimum_required( VERSION 2.4 ) if( COMMAND cmake_policy ) cmake_policy( SET CMP0003 NEW ) endif( COMMAND cmake_policy ) # # Unix Target Constants # add_definitions( -DUNIX ) include( CheckCSourceCompiles ) include( CheckLibraryExists ) set( RELVER "2.2.1" ) subdirs( source/iked source/ikec source/libike source/libip source/libidb source/libith source/liblog source/libpfk ) set( SEARCH_INC /usr/local/include /usr/include ) set( SEARCH_LIB /usr/local/lib /usr/lib ) set( SEARCH_BIN /usr/local/bin /usr/pkg/bin /usr/bin ) set( SEARCH_SYS /usr/local /usr/share /usr ) # # Apple OSX Target Constants # if( APPLE ) set( CMAKE_OSX_ARCHITECTURES "x86_64" ) set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-declarations" ) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-declarations" ) endif( APPLE ) # # Path Option Checks # if( NOT EXISTS ${CMAKE_INSTALL_PREFIX} ) set( CMAKE_INSTALL_PREFIX "/usr" ) endif( NOT EXISTS ${CMAKE_INSTALL_PREFIX} ) message( STATUS "Using install prefix ${CMAKE_INSTALL_PREFIX} ..." ) # etc install path if( ETCDIR ) set( PATH_ETC ${ETCDIR} ) else( ETCDIR ) if( EXISTS ${CMAKE_INSTALL_PREFIX}/etc ) set( PATH_ETC "${CMAKE_INSTALL_PREFIX}/etc" ) else( EXISTS ${CMAKE_INSTALL_PREFIX}/etc ) set( PATH_ETC "/etc" ) endif( EXISTS ${CMAKE_INSTALL_PREFIX}/etc ) endif( ETCDIR ) message( STATUS "Using etc install path ${PATH_ETC} ..." ) # bin install path if( BINDIR ) set( PATH_BIN ${BINDIR} ) else( BINDIR ) if( EXISTS ${CMAKE_INSTALL_PREFIX}/bin ) set( PATH_BIN "${CMAKE_INSTALL_PREFIX}/bin" ) else( EXISTS ${CMAKE_INSTALL_PREFIX}/bin ) set( PATH_LIB "/usr/bin" ) endif( EXISTS ${CMAKE_INSTALL_PREFIX}/bin ) endif( BINDIR ) message( STATUS "Using bin install path ${PATH_BIN} ..." ) # sbin install path if( SBINDIR ) set( PATH_SBIN ${SBINDIR} ) else( SBINDIR ) if( EXISTS ${CMAKE_INSTALL_PREFIX}/sbin ) set( PATH_SBIN "${CMAKE_INSTALL_PREFIX}/sbin" ) else( EXISTS ${CMAKE_INSTALL_PREFIX}/sbin ) set( PATH_SBIN "/usr/sbin" ) endif( EXISTS ${CMAKE_INSTALL_PREFIX}/sbin ) endif( SBINDIR ) message( STATUS "Using sbin install path ${PATH_SBIN} ..." ) # lib install path if( LIBDIR ) set( PATH_LIB ${LIBDIR} ) else( LIBDIR ) if( EXISTS ${CMAKE_INSTALL_PREFIX}/lib ) set( PATH_LIB "${CMAKE_INSTALL_PREFIX}/lib" ) else( EXISTS ${CMAKE_INSTALL_PREFIX}/lib ) set( PATH_LIB "/usr/lib" ) endif( EXISTS ${CMAKE_INSTALL_PREFIX}/lib ) endif( LIBDIR ) message( STATUS "Using lib install path ${PATH_LIB} ..." ) # man install path if( MANDIR ) set( PATH_MAN ${MANDIR} ) else( MANDIR ) find_path( PATH_MAN NAMES "man" PATHS ${SEARCH_SYS} NO_DEFAULT_PATH ) if( PATH_MAN ) set( PATH_MAN "${PATH_MAN}/man" ) else( PATH_MAN ) set( PATH_MAN "${CMAKE_INSTALL_PREFIX}/man" ) endif( PATH_MAN ) endif( MANDIR ) message( STATUS "Using man install path ${PATH_MAN} ..." ) if( KRNINC ) set( INC_KERNEL_DIR ${KRNINC} ) message( STATUS "Using kernel include path ${INC_KERNEL_DIR} ..." ) endif( KRNINC ) # # PreRequisite Checks # check_library_exists( "crypt" "crypt" "" FUNC_LIB_CRYPT ) find_path( PATH_INC_CRYPTO NAMES "openssl/evp.h" PATHS ${SEARCH_INC} ) if( NOT PATH_INC_CRYPTO ) message( FATAL_ERROR "Unable to locate openssl crypto include files" ) endif( NOT PATH_INC_CRYPTO ) find_library( PATH_LIB_CRYPTO NAMES "crypto" PATHS ${SEARCH_LIB} ) if( NOT PATH_LIB_CRYPTO ) message( FATAL_ERROR "Unable to locate openssl crypto library file" ) endif( NOT PATH_LIB_CRYPTO ) find_path( PATH_INC_EDIT NAMES "histedit.h" PATHS ${SEARCH_INC} ) if( NOT PATH_INC_EDIT ) message( FATAL_ERROR "Unable to locate libedit include files" ) endif( NOT PATH_INC_EDIT ) find_library( PATH_LIB_EDIT NAMES "edit" PATHS ${SEARCH_LIB} ) if( NOT PATH_LIB_EDIT ) message( FATAL_ERROR "Unable to locate libedit library file" ) endif( NOT PATH_LIB_EDIT ) find_package(Threads) message( STATUS "Using library ${CMAKE_THREAD_LIBS_INIT}" ) if( NOT CMAKE_USE_PTHREADS_INIT ) message( FATAL_ERROR "Unable to locate required package : pthreads" ) endif( NOT CMAKE_USE_PTHREADS_INIT ) if( NOT APPLE ) check_library_exists( ${CMAKE_THREAD_LIBS_INIT} "pthread_mutex_timedlock" "" FUNC_LIB_TIMEDLOCK ) endif( NOT APPLE ) if( FUNC_LIB_TIMEDLOCK ) add_definitions( -DOPT_TIMEDLOCK ) endif( FUNC_LIB_TIMEDLOCK ) find_program( PATH_BIN_FLEX NAMES "flex" PATHS ${SEARCH_BIN} ) if( NOT PATH_BIN_FLEX ) message( FATAL_ERROR "Unable to locate required binary : flex" ) endif( NOT PATH_BIN_FLEX ) message( STATUS "Using binary ${PATH_BIN_FLEX} ..." ) find_program( PATH_BIN_BISON NAMES "bison" PATHS ${SEARCH_BIN} ) if( NOT PATH_BIN_BISON ) message( FATAL_ERROR "Unable to locate required binary : bison" ) endif( NOT PATH_BIN_BISON ) message( STATUS "Using binary ${PATH_BIN_BISON} ..." ) find_path( PATH_INC_NETIPSEC NAMES "ipsec.h" PATHS "/usr/include/netipsec" ) if( PATH_INC_NETIPSEC ) add_definitions( -DOPT_NETIPSEC ) endif( PATH_INC_NETIPSEC ) find_library( PATH_LIB_RT NAMES "rt" PATHS ${SEARCH_LIB} ) find_path( PATH_INC_PFKEYV2 NAMES "net/pfkeyv2.h" "linux/pfkeyv2.h" PATHS ${SEARCH_INC} ${INC_KERNEL_DIR} ) if( NOT PATH_INC_PFKEYV2 ) message( FATAL_ERROR "Unable to locate system pfkeyv2 include file" ) endif( NOT PATH_INC_PFKEYV2 ) # # Build Option Checks # OPTION( DEBUG "include Debug Symbol support" ) OPTION( NATT "include NAT Traversal support" ) OPTION( LDAP "include LDAP Authentication support" ) OPTION( QTGUI "include Client QT GUI support" ) OPTION( TESTS "include library test programs" ) OPTION( ETCDIR "custom etc install path" ) OPTION( BINDIR "custom bin install path" ) OPTION( SBINDIR "custom sbin install path" ) OPTION( LIBDIR "custom library install path" ) OPTION( MANDIR "custom man page install path" ) # Debug Symbols Option if( DEBUG ) add_definitions( -g ) endif( DEBUG ) # NAT Traversion option if( NATT ) if( NOT APPLE ) check_c_source_compiles( " #ifdef __linux__ # include # include #else # include # include #endif int main() { struct sadb_x_nat_t_type test; return 0; } " NATT_FOUND ) else( NOT APPLE ) set( NATT_FOUND TRUE ) endif( NOT APPLE ) if( NOT NATT_FOUND ) message( FATAL_ERROR "Unable to locate required NAT-T pfkey structures" ) endif( NOT NATT_FOUND ) # success message( STATUS "Enabled NAT Traversal support ..." ) add_definitions( -DOPT_NATT ) endif( NATT ) # LDAP support option if( LDAP ) # ldap include find_path( PATH_INC_LDAP NAMES "ldap.h" PATHS ${SEARCH_INC} ) if( NOT PATH_INC_LDAP ) message( FATAL_ERROR "Unable to locate LDAP include file" ) endif( NOT PATH_INC_LDAP ) # ldap libraries find_library( PATH_LIB_LDAP NAMES "ldap" PATHS ${SEARCH_LIB} ) find_library( PATH_LIB_LBER NAMES "lber" PATHS ${SEARCH_LIB} ) if( NOT PATH_LIB_LDAP OR NOT PATH_LIB_LBER ) message( FATAL_ERROR "Unable to locate LDAP library file" ) endif( NOT PATH_LIB_LDAP OR NOT PATH_LIB_LBER ) # success message( STATUS "Enabled LDAP Authentication support ..." ) add_definitions( -DOPT_LDAP ) endif( LDAP ) # Client GUI option if( QTGUI ) add_definitions( -DQT_THREAD_SUPPORT ) find_package( Qt4 COMPONENTS QtCore QtGui REQUIRED ) if( NOT QT_QTGUI_FOUND ) message( FATAL_ERROR "Unable to locate required package : QT" ) endif( NOT QT_QTGUI_FOUND ) # success message( STATUS "Enabled Client QT GUI support ..." ) if( APPLE ) add_subdirectory( source/libqt ) endif( APPLE ) add_subdirectory( source/qikea ) add_subdirectory( source/qikec ) endif( QTGUI ) # Library Test Programs if( TESTS ) message( STATUS "Building library test programs ..." ) add_subdirectory( source/test_ith ) endif( TESTS ) ike-2.2.1+dfsg/CONTRIB.TXT000066400000000000000000000002741223036517100147070ustar00rootroot00000000000000This file lists major source code contributions to the Shrew Soft VPN Client. NAME : Robert Nelson DATE : 02-04-2009 Added support for negotiating Cisco UDP encapsulation of ESP packets. ike-2.2.1+dfsg/LICENSE.TXT000066400000000000000000000036721223036517100146760ustar00rootroot00000000000000Copyright (c) 2006-2013 Shrew Soft Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Redistributions in any form must be accompanied by information on how to obtain complete source code for the software and any accompanying software that uses the software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs. THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC 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. ike-2.2.1+dfsg/README.TXT000066400000000000000000000366201223036517100145500ustar00rootroot00000000000000================================================================================ ABOUT ================================================================================ This software distribution contains the Shrew Soft Inc Internet Key exchange daemon and IPsec VPN client front end applications. All included source code and supporting materials are covered under a liberal open source license. Please see the LICENSE.TXT file for more details. The source code is organized as several components that work together to facilitate IPsec communications. iked - Internet Key Exchange Daemon This component implements the IKE protocol version 1 for IPv4 networks and is very similar to the IPsec tools racoon daemon. It supports an extensive feature set that includes NAT-Traversal, Dead Peer Detection, Mode Config for centralized client configuration and management, dynamic security policy configuration and dynamic route management. The daemon supports two different modes of operation depending on how it is configured. This first mode of operation allows it to interact with Client Front end applications to facilitate Client to Gateway remote access. The other mode allows it to facilitate site to site IPsec key exchange provide advanced client gateway functionality. At this time, is recommended that the daemon only be used in client mode due to lack of adequate testing. If you need to install a VPN Client Gateway, please use the IPsec Tools racoon daemon. Version 0.7 or later is highly recommended. ikec - VPN Client Connect Application This component provides a console based user interface that represents a connection instance for a remote site. It allows a user to connect or disconnect, enter user login credentials and view the status of the remote access connection. qikea - VPN Access Manager Application ( optional ) This component provides a GUI user interface for managing remote site configurations. It is also used to launch a VPN Client Connect instance for a given remote site. qikec - VPN Client Connect Application ( optional ) This component provides a GUI user interface that represents a connection instance for a remote site. It allows a user to connect or disconnect, enter user login credentials and view the status of the remote access connection. ================================================================================ REQUIREMENTS ================================================================================ This section describes the basic requirements used to compile this software. In most cases, development versions of the dependencies will need to be installed. These could be available as pre-compiled packages or compiled directly from source. Minimum -------------------------------------------------------------------------------- c++ compiler stock c libs stock c includes pthread support lex or flex libedit bison >= 2.3 cmake >= 2.4 opsenssl >= 0.9.x This software requires Bison version 2.3 or higher as it uses the new c++ parser model. The c++ model was introduced in version 2.1 but appears to be incomplete. Optional -------------------------------------------------------------------------------- TrollTech QT >= 4.2 openldap >= 2.0 The Trolltech QT toolkit version 4.2.x or higher is also required if you plan to build the QT client front end applications. The openldap support is only useful if you plan to use iked to facilitate VPN client gateway connectivity and require xauth support via an external LDAP database. ================================================================================ PLATFORM SUPPORT ================================================================================ The FreeBSD, NetBSD and several Linux operating systems are supported and have been tested with this software. A free windows client is also available but requires custom kernel support and additional software that is not covered under an open source license. Please see the Shrew Soft Inc web site for more details. The only processor architectures that have been tested are i386 and amd64. It may be that this software works with more exotic architectures such as powerpc or sparc but no testing has been performed to confirm this. With the exception of the Windows client, this software utilizes the native IPsec kernel support which is bundled with all supported operating systems. Depending on your platform, a custom kernel may need to compiled or additional kernel modules may need to be loaded before it will operate correctly. Please see the specific platform notes for more details. FreeBSD -------------------------------------------------------------------------------- FreeBSD version 6.2 RELEASE was used to test this software. You will need to make sure your kernel has been built with IPsec support. Either the KAME IPsec stack or the Fast IPsec stack is supported. For example, to add support for Fast IPsec you could enable the following options in your custom kernel configuration file ... # IP Security device crypto options FAST_IPSEC As of FreeBSD 6.2, NATT kernel support has not yet been committed to the main line source. However, a high quality patch is available and has been tested with this software. It can be obtained from the following url ... http://ipsec-tools.sourceforge.net/freebsd6-natt.diff Before this software can be compiled with NATT support, the patch must be applied to your kernel. To apply the patch, you need to copy the file into your /usr/src/sys directory and apply it using the following command ... patch < freebsd6-natt.diff To enable this support, include the additional option in your custom kernel configuration file ... options IPSEC_NAT_T You will then need to build and install the custom kernel and perform a buildworld and installworld. Please see the FreeBSD handbook for more information on compiling and installing a custom kernel and userland. The following options are recommended when running the cmake configuration for FreeBSD. Please see the OPTIONS section for more details. cmake -DQTGUI=YES -DNATT=YES NetBSD -------------------------------------------------------------------------------- NetBSD version 3.1 was used to test this software. You will need to make sure your kernel has been built with IPsec support. For example, to include support for IPsec you could enable the following options in your custom kernel configuration file ... options INET options IPSEC options IPSEC_ESP options IPSEC_NAT_T Please see the NetBSD Documentation for more information on compiling and installing a custom kernel. The following options are recommended when running the cmake configuration for NetBSD. Please see the OPTIONS section for more details. cmake -DQTGUI=YES -DNATT=YES -DETCDIR=/etc NetBSD also appears to require several environment variables to be set when compiling and using the QT front end applications. For example, the following lines were added to the users ~/.profie script when testing this software for NetBSD ... QTDIR=/usr/pkg/qt4 QMAKESPEC=netbsd-g++ PATH=${PATH}:${QTDIR}/bin LD_LIBRARY_PATH=/usr/pkg/qt4/lib/:/usr/X11R6/lib export PATH QTDIR QMAKESPEC LD_LIBRARY_PATH Linux -------------------------------------------------------------------------------- Beginning with linux version 2.6, native kernel support has been added for the IPsec protocol suite. Both the Fedora Core 6 and Ubuntu 7.04 distributions were tested and came preinstalled with both ESP and NAT-T support by default. If you use another distribution, a custom kernel or additional modules may be be required. Please see your distribution documentation for more details. The following options are recommended when running the cmake configuration for linux platforms. Please see the OPTIONS section for more details. cmake -DCMAKE_INSTALL_PREFIX=/usr -DQTGUI=YES -DETCDIR=/etc -DNATT=YES For 64 bit Linux systems, most distributions store native 64bit library files in a unique path. The option for this is -LIBDIR=/usr/lib64 or the appropriate directory path. NOTE : It may also be necessary to add the KRNINC option to specify the kernel header file path on older versions of Linux. OSX -------------------------------------------------------------------------------- Apple OSX provides native kernel support for the IPsec protocol suite. This software was designed to support OSX version 10.8 and later. This software can also be linked against a private Qt library build when gui components are desired. When an install step is performed, a private copy of the Qt libs will also be installed. All references to that library will be modified to utilize the private library path. The following options are recommended when running the cmake configuration for OSX platforms. Please see the OPTIONS section for more details. cmake -DQTGUI=YES -DNATT=YES -DCMAKE_INSTALL_PREFIX=/usr \ -DQT_QMAKE_EXECUTABLE=[/qt/install/path]/bin/qmake NOTE : Qt will still attempt to load plugin libraries from the original private Qt install path. Since these libraries will have references to the original Qt library framework paths ( not the copy ), the dynamic link loader may load multiple versions of Qt libraries and cause the application to crash. It may be necessary to move the private qt install path to a different location before executing the compiled gui applications. For example: mv /qt/install/path /qt/install/path.bak ================================================================================ COMPILING ================================================================================ The cmake build system is used to generate platform specific make files. To configure the build, you simply run cmake in the base distribution directory using any optional parameters you may require. For example: enter the following to build and install the basic software ... cmake [OPTIONS] make make install ================================================================================ OPTIONS ================================================================================ In addition to the standard CMake options such as CMAKE_INSTALL_PREFIX, a few additional build parameters may be specified. Here is a brief list ... DEBUG Enable Debug Symbols TESTS Enable Library Tests Build QTGUI Enable Client QT GUI NATT Enable Nat Traversal Support LDAP Enable LDAP Authentication Support ETCDIR Custom etc configuration install path BINDIR Custim user bin install path SBINDIR Custim user sbin install path LIBDIR Custom user lirbrary install path MANDIR Custom man page install path KRNINC Kernel include path For example: enter the following to build and install the software with a few common options enabled ... cmake -DDEBUG=YES -DQTGUI=YES -DNATT=YES -DLDAP=YES make make install ================================================================================ USAGE ================================================================================ The main process that handles IKE negotiations is iked and must be run as root. By default, it will detach itself from the terminal and execute as a daemon. To force foreground operation, use the -F switch. A sample configuration file is included in this distribution and will be installed in the etc system configuration directory. The configuration should be suitable to allow for client operation but can also be modified to allow for site to site or client gateway operation as well. See the iked.conf man page for more details. Once the iked process has been launched, the VPN Access Manager application ( qikea ) is used to build remote access client configurations and initiate client connections. When the Access Manager GUI is used to initiate a client connection, a VPN Connect application ( qikec ) process is created. This process interacts with iked to initiate the connection. Alternately, a command line version of the VPN Connect application ( ikec ) can be used to initiate a connection. Please see the online documentation available at http://www.shrew.net for more details. ================================================================================ EXPORTED CONFIGURATION FILES ================================================================================ A site configuration contains all the data required to connect to a site using the VPN client tools. These configuration files can be exported or imported using the VPN Access Manager application. The file format used to describe the site configuration is a text ducument that contains one attribute per line with one or more attribute values. The attribute type is denoted by a single charachter field followed by the attribute name field and then by a value. The fields are separated using a colon charachter. For example, the following line describes a string attribute names network-host with a value of 10.1.1.1 s:network-host:10.1.1.1 Attributes are denoted as one of three types. s = String n = Number b = Binary ( bas64 encoded ) Multi valued strings are separated using a comma charachter and binary values are base64 encoded. Here is a list of attributes currently supported. s:network-host:| n:network-ike-port: s:network-auto-mode:disable|pull|push|dhcp s:client-iface:virtual|direct n:client-addr-auto:0|1 s:client-ip-addr: s:client-ip-mask: n:network-mtu-size: n:client-wins-used:0|1 n:client-wins-auto:0|1 s:client-wins-addr: n:client-dns-used:0|1 n:client-dns-auto:0|1 s:client-dns-addr: s:client-dns-suffix: n:client-splitdns-used:0|1 n:client-splitdns-auto:0|1 s:client-splitdns-list: s:network-natt-mode:disable|enable|force-draft|force-rfc s:network-frag-mode:disable|enable|force n:network-dpd-enable:0|1 n:network-notify-enable:0|1 n:client-banner-enable:0|1 s:auth-method:hybrid-rsa-xauth|mutual-rsa-xauth|mutual-psk-xauth|mutual-rsa|mutual-psk s:auth-server-cert: s:auth-client-cert: s:auth-client-key: b:auth-mutual-psk: s:ident-client-type:asn1dn|keyid|fqdn|ufqdn|address s:ident-client-data: s:ident-server-type:asn1dn|keyid|fqdn|ufqdn|address s:ident-server-data: s:phase1-exchange:main|aggressive s:phase1-cipher:auto|aes|blowfish|3des|cast|des n:phase1-keylen: ( 0 = auto ) s:phase1-hash:auto|md5|sha1 n:phase1-dhgorup:1|2|5|14|15 n:phase1-life-secs: n:phase1-life-kbytes: s:phase2-transform:auto|esp-aes|esp-blowfish|esp-3des|esp-cast|esp-des n:phase2-keylen: ( 0 = auto ) s:phase2-hmac:auto|md5|sha1 n:phase2-pfsgroup:-1|0|1|2|5|14|15 ( -1 = disabled, 0 = auto ) n:phase2-life-secs: n:phase2-life-kbytes: s:policy-level:auto|required|unique|shared n:policy-nailed:0|1 ( persistent IPsec SAs ) n:policy-list-auto:0|1 s:policy-list-exclude:
s:policy-list-include:
NOTE : When a file is exported, the certificate and key file paths are modified to only contain the unqualified filename. The actual file data is encoded as a binary value. This allows the certificate information to be exported along with other site configuration data. Here are the related attributes after export. s:auth-server-cert: b:auth-server-cert-data: s:auth-client-cert: b:auth-client-cert-data: s:auth-client-key: b:auth-client-key-data: ike-2.2.1+dfsg/TODO.TXT000066400000000000000000000437711223036517100143650ustar00rootroot00000000000000---------------------------------------------------------------------- VPN Client ---------------------------------------------------------------------- Alpha release ... ---------------------------------------------------------------------- X Resolve host dns to address in ipsecc X Transmit size in vnet driver X DHCP renew effects phase2 sa's X Client status message rework X Allow the configuration of the dns suffix in ipseca X NAT-T force option in ipseca & ipsecc X Manual config of client settings in ipsecd ( review ipseci ) X Key size in ipseca for phase1 X Dir path problem ipsecc & ipsecd X Pre-fragment support in ipsecd X Update logging facility in ipsecd X Use generic logging facility in dll classes X Test all dialog options for feature parity Beta release ... ---------------------------------------------------------------------- X Rewrite vnet driver X Create cleanup routines for all sa and tunnel objects X Fix license view in about dialog X Delete sa's after they are declared dead X Isakmp re-transmit in ipsecd X Send NAT keep-alive packets X Mutual auth XAuth mode 1.0.0 release ... ---------------------------------------------------------------------- X SPI size of 8 in sa payload X Flag tunnel as dead when proposal is rejected X Handle notification payloads when bundled in phase1 or phase2 X Correct dialog layout issues X Allow for disabled client WINS and DNS settings X IKE fragmentation X Send delete messages as outlined in RFC 2408 X Handle delete messages as outlined in RFC 2408 X Send notify messages as outlined in RFC 2408 X Handle notify messages as outlined in RFC 2408 X Client feedback for failure cases X Fix crash after items deleted in ipseca X Support the modecfg banner attribute X Cleanup IPFRAG class X Phase2 sa re-establish after expire X Create debugger application interface X Prevent multiple tunnels from using the same gateway X Support the pfs modecfg attribute X Support the split exclude modecfg attribute X Correct client busy loop bug X Pre-configured client packaging system X Fix multiple tunnel issues X Write documentation X Button default issue in ipsecc X Test non-admin user operation X Correct loss of default route X Correct the VNET MTU dropping to 175 X Update VProt Interface to handle Dialup Adapters 1.1.0 release - Bug fixes and fine tuning ---------------------------------------------------------------------- X Add Split DNS Support X Cleanup orphaned dnsfwd entries X Cleanup PACKET_DNS memory leaks X Add Dead Peer Detection responder X Add Dead Peer Detection initiator X Move away from dynamic adapter creation ( adapter pools ) X Correct phase2 negotiation issues X Replace DHCP support with static configuration X Fix session termination messages X Move remaining projects in-branch to share versions X Modify interfaces to support Split DNS, DPD Banner and Notify X Remove tunnel references to internal API X Standardize and fix validation of inform and config hashes X Audit use of random generation X Correct debug output for modecfg banner X Restructure SDB and packet resend X Resolve issue with devcfg initial device creation X Report phase 2 id types and values X Add client username and password command line options X Remove media sense from VNet driver X Track down a rare ipsecc freeze when server rudely disconnect X Review driver locking X Modify VProt to handle multiple dialup adapters X Review adapter registry configurtaion X Update release documentation X Look into reported issue with Split DNS X Implement Split DNS reverse lookups X Correct p12 related problems X Add support for encrypted p12 and pem files X Correct problems with local ID checking X Test kernel drivers with multi-core systems 2.0.0 release - Interface below TCPIP and friends ---------------------------------------------------------------------- X Replace Protocol driver with IM filter driver X Build rule based filter framework into IM driver X Implement divert/mirror rule processing ( like FreeBSD ipfw ) X Implement accept/reject rule processing X Use filter framework for packet inspection / redirection X Remove uneeded functionality from virtual network interface X Hide platform specific route index detail in libip X Add support for using a real interface as a tunnel endpoint X Review locking and stabilize IM filter driver X Modify transparent DNS proxy code to work in direct or virtual mode X Modify IM filter driver to support rule priorities for insertion X Modify libflt ethernet header creation routine to use ARP data X Modify ipsecd, vflt and libvflt to deal with transient devices X Add auto configuration for phase1 and phase2 parameters X Review and correct any issues with the exchange handlers X Rewrite code related to proposal generation and checking X Rewrite code related to policy management X Fix ipsecd internal structure exposure to ipsecc X Rewrite ipsec processing code to be policy driven X Add support for ah in ipsecd X Add support for ipcomp and deflate compression X Rewrite packet queuing system X Add ability to view FW rules in VPN Trace X Add support for bundled proposals X Seperate ike process, ipsec control and ipsec process threads X Split ipsec daemon into ipsecd and iked X Port iked to a single unix target X Build pfkey interface for SPD and SAD management X Add ability to view SPD and SAD entries in VPN Trace X Fix information exchange and notify support X Add iked config file support for unix targets using flex/bison X Add iked support for sending responder lifetime notifications X Add iked support for xauth via local and ldap sources X Add iked support for modecfg X Add iked support for advanced policy generation X Split DNS Transparent proxy support into dtpd X Remove optional esp packet pre-fragmentation from ipsecd X Review all db locking and entry removal X Improve phase2 rekey in ipsecd X Add tunnel route to peer with default route X Modify existing default route metric X Add iked and iked.conf man pages X Fix initial vnet device usage X Add support for config push mode X Modify the client gui for manual policy include/exclude X Modify the client gui for config push or pull X Fix the vpn trace sdb output tabs X Update the client gui network tab X Test all client features against racoon and iked X Update the documentation 2.0.1 release - Improve platform support ---------------------------------------------------------------------- X Add support for Windows XP amd64 platform X Add support for x86/amd64 FreBSD platforms X Add support for x86/amd64 NetBSD platforms X Add support for x86/amd64 Linux platforms 2.0.2 release - Bug fix and fine tuning ---------------------------------------------------------------------- X Various bug fixes 2.0.3 release - Bug fix and fine tuning ---------------------------------------------------------------------- X various bug fixes 2.1.0 release - Improve platform and gateway support ---------------------------------------------------------------------- X Review option flag usage for client struct X Make divert rule management dynamic ( be nice to other clients ) X Add support for syslog output on unix targets X Add support for DHCP over IPsec configuration method X Add support for strictly manual client configuration method X Add stateful fragment evaluation to filter driver X Add batched packet send and recv support to filter driver X Add support for older Linux distributions X Fix errors associated with iked processing duplicate packets X Fix validation and trimming of trailing packet data X Fix IM driver conflicts with the Cisco VPN Client ( DNE driver ) X Use exchange specific re-send timeout handlers for better logging X Fix iked to work with any udp service port X Add site connection support using the access manager system tray X Add iked support for multiple DNS/WINS server addresses X Add support for NAT-T draft 00 and 01 versions X Fix IM driver issues with Windows 2K and Virtualization Software X Add support for specifying the virtual network adapter MTU X Add DNS and WINS support for direct adapter mode X Fix Split DNS to work with an adapter specific default domain X Add support for Windows x86/amd64 Vista platforms X Fix route management for tunnels that force all traffic X Add support for renegotiating IKSAMP SAs in client mode X Add support for persistent IPSEC SAs X Add support for site configuration file format versioning X Add support for storing key and cert data in the site config X Add user preference dialog for site manager X Add preference for client minimize to system tray X Add preference for pre-populating user names X Add timestamps for non-syslog log output X Add checks for illegal site configuration names X Add site name and file conflict resolution dialogs X Fix any differences between unix and windows site configuration X Fix dissapearing DNS settings when the connection fails X Fix the event timer class to avoid wakeups X Fix hangs on *nix targets during iked shutdown X Add work around for missing xauth type attribute X Add a generic IPC class to avoid wakeups and reduce latency X Port libdtp to use generic IPC class X Port libike to use generic IPC class X Port libpfk to use generic IPC class X Fix high number of select wakeups on socket calls X Fix the client statistics update X Fix MS dnscache problems the right way X Import new logo and improved icon sets X Fix DPD problems while transitioning between ISAKMP SAs X Improve DPD timeout algorithm X Provide non WHQL signed Vista drivers X Correct NDIS 6 miniport compatibility issue with filter driver X Validate and document support for Cisco ASA gateways X Validate and document support for Juniper SSG gateways X Validate and document support for Zywall gateways X Validate and document support for Fortigate gateways 2.1.1 release - Bug fix and fine tuning ---------------------------------------------------------------------- X Fix NDIS 6 miniport problems with filter driver X Fix VPN Trace problems on 64 bit Windows targets 2.1.2 release - Bug fix and fine tuning ---------------------------------------------------------------------- X Various platform specific bug fixes 2.1.3 release - Bug fix and fine tuning ---------------------------------------------------------------------- X Fix Diffie Hellman negotiation failures X Fix mature SA packet re-transmit issues X Fix config mode packet retransmit issues X Add checks for mandatory reboot post install on Windows Platforms X Fix dns resoltion for names that begin with numeric digit 2.1.4 release - Bug fix and fine tuning ---------------------------------------------------------------------- X Fix a thread state bug that caused phase2 to fail in rare cases X Fix a phase2 responder bug that caused packet re-transmit to fail X Add explicit link state notifications for Vista filter drivers X Fix quick disconnects after negotiating with a cisco gateway X Add Dialup/PPP adapter support for Vista Platforms X Fix a critical bug in the windows libvflt ip forward caching code X Add proper support for multiple NAT-T hash values 2.1.5 release - Bug fix and fine tuning ---------------------------------------------------------------------- X Add support for Cisco hybrid mode authentication ( mutual group ) X Add support for Cisco PCF file import X Add support for auto uninstall during install of Windows package X Add support for the XAuth radius chap method X Add support for correctly handling multiple certificate requests X Fix Checkpoint authentication regressions X Fix reported link speed issue with virtual network driver X Fix various kernel driver related issues reported by users X Fix problems with resolv.conf file generation on unix platforms X Fix NAT-T configuration issue 2.1.6 release - Bug fix and fine tuning ---------------------------------------------------------------------- X Fix problem with direct adapter mode DNS configuration X Fix DHCP over IPsec via DHCP adapters by immitating a bootp relay X Fix DHCP pool exhaustion issue by retaining fake MAC see value X Fix ESP payload padding issue with Adtran gateways X Fix runtime creation of virtual adapter instances on Vista/7 X Fix dropped packets issues with vflt socket wrappers X Fix uninstall issue that occured when Novell client was installed X Fix kernel driver crash due to WANLINE (PPP/PPTP) notify parsing X Fix various kernel driver issues blocking DTM controller tests X Fix a bug related to using the IKE Fragmentation extestion X Fix a bug in IKE push mode that called a pull handler instead X Use a different port for DNS proxy to avoid 3rd party conflicts X Add support for overlapping local and remote networks X Add support for shared policy generation mode X Add manifest files so users are prompted for elevated privileges X Add pid file support on Linux/BSD platforms X Add support for reporting the UNITY app version and firewall type X Improve adapter/address selection for multiple inet connections X Initial kernel driver versions signed by Microsoft WHQL 2.1.7 release - Bug fix and fine tuning ---------------------------------------------------------------------- X Fix negotiation of tunnel-all ( 0.0.0.0/0 ) configurations in iked X Fix inbound SA negotiation with shared policy generation mode X Fix iproute deletion issue on Vista/7 platforms X Fix import of PCF files with non-encrypted password X Apply IPsec policy and filename promts fixed from Michael Kenny X Improve DNS Proxy divert rule management 2.2.0 release - Major feature improvements ---------------------------------------------------------------------- X Add Qt4 gui components to replace Qt3 components on Linux/BSD X Add console based VPN Connect component on Linux/BSD ( non-gui ) X Add initial support for Intel Mac OSX platforms w/ DMG installer X Add an option for selecting a randomized virtual subnet address X Add GUI support for multiple DNS/WINS server addresses X Add support for automatic stable software update checks X Add text that displays the connection time in system tray tooltip X Add support for Sidewinder 6.x, 7.x gateways ( merged to 2.1.x ) X Add support for Netgear gateways ( merged to 2.1.x ) X Fix secrity flaws in the ipc server admin code X Fix slow responsiveness duing DHCP over IPsec negotiations X Fix reverse DNS lookup issues with DNS proxy daemon X Make the client config subordinate to the phase1 handle X Use bdata instead of openssl key struct pointer in keyfile code X Use overlapped IO to interface with the windows filter driver X Fix the 500ms wakeup issue by avoiding vflt select-like calls X Fix all memory leaks reported by various debugging tools X Fix TCP LSO task offload in vflt driver on Vista/7 platforms X Fix WLAN virtual adapter issue reported on mailing list X Fix dialog color issues for windows HCB accessibility modes X Fix keyboard navigation to site profiles in access manager X Fix reported problems with DHCP over IPsec X Add support for newer openssl supported message auth algorithms X Add support for both ike and pfs dh groups 16, 17 and 18 X Add support for unattended installations ( needs signed drivers ) X Make all client platforms use file based site configurations X Make certificate data an embedded component of the site config X Add support for public site configurations on Windows Platforms X Fix handling of low-power-state notifications in iked on Windows . Add support for Secure Domain Login on Vista/7 platforms . Investigate PPP with Virtual Adapter DNS preference issue . Improve support for automatic stable software update checks . Cleanup registry based site configuration data . Test all rsa key file scenarios that use password protection 2.2.1 release - Bug fix and fine tuning ---------------------------------------------------------------------- . Fix or add all documented command line options in iked . Add support for encrypted site configuration storage . Cleanup all references to the obsolete COMPAT policy mode . Fix DNS setting issues with newer Mac OSX platforms . Add support for two factor user authentication methods . Apply Qt4 French translation patch from Alexis Lagoutte Near Term Goals ---------------------------------------------------------------------- . Validate USB WIFI/Ethernet adapter support on Windows Platforms . Validate and document support for OpenBSD gateways . Validate and document support for Strong/OpenSWAN gateways . Validate and document support for SonicWall gateways x Validate and document support for Checkpoint gateways . Validate and document support for Lancom gateways . Cleanup libpfk, its really ugly . Fix static buffer usage for temporary string data ? Use Qt4 to build unified cross platform GUI components ? Add ability to drag site connections as shortcuts ? Add support for client connect/disconnect script execution ? Add adaptive communications during connect ( Frag/NATT ) ? Move to a purely primitive based tunnel confguration interface ? Add support for lzs compression ( patent encumbered ) ? Add support for microsoft certificate and key storage api Long Term Goals ---------------------------------------------------------------------- . Fix the server mode support in iked . Write a setkey replacement based on libpfk . Stateful client side firewall . Create lightweight kernel or userland buildable crypto library . Move ip security processing into the kernel ---------------------------------------------------------------------- pfSense ---------------------------------------------------------------------- X Add support for modecfg X Add support for Xauth . Add support for fine grained network access control ---------------------------------------------------------------------- IPSEC-TOOLS ---------------------------------------------------------------------- X LDAP auth module X Group based sainfo selection X Group based xauth X isakmp_id2str X sainfo debug improvements X responder ignores inital fragment X clientaddr . review sa cleanup after client disconnect . cleanup modeconfg and introduce ike push mode . negotiate unity firewall rulesets via modecfg ike-2.2.1+dfsg/package/000077500000000000000000000000001223036517100145765ustar00rootroot00000000000000ike-2.2.1+dfsg/package/macosx/000077500000000000000000000000001223036517100160705ustar00rootroot00000000000000ike-2.2.1+dfsg/package/macosx/build-package.sh000077500000000000000000000013231223036517100211160ustar00rootroot00000000000000#!/bin/sh rm -f ./vpn-client-install.dmg /usr/local/bin/freeze vpn-client-install.packproj VOLNAME="Shrew Soft VPN Client Install" mv build "$VOLNAME" cp ../../LICENSE.TXT "./$VOLNAME" sudo /usr/bin/hdiutil create -ov -format UDRW -srcfolder "./$VOLNAME" ./vpn-client-install.dmg mkdir ./vol sudo /usr/bin/hdiutil attach ./vpn-client-install.dmg -readwrite -noautoopen -mountpoint ./vol/ /bin/cp ./vpn-client-volume.icns ./vol/.VolumeIcon.icns /Developer/Tools/SetFile -a -C ./vol sudo /usr/bin/hdiutil detach ./vol/ rmdir ./vol sudo /usr/bin/hdiutil convert ./vpn-client-install.dmg -format UDZO -o ./vpn-client-install-ro.dmg /bin/mv -f ./vpn-client-install-ro.dmg ./vpn-client-install.dmg rm -fr "./$VOLNAME" ike-2.2.1+dfsg/package/macosx/script.postinstall000077500000000000000000000004421223036517100216750ustar00rootroot00000000000000#!/bin/sh # copy the sample iked.conf file to the active file /usr/bin/sudo /bin/cp /etc/iked.conf.sample /etc/iked.conf # setup iked for control under launchd /usr/bin/sudo /bin/launchctl load /Library/LaunchDaemons/net.shrew.iked.plist /usr/bin/sudo /bin/launchctl start net.shrew.iked ike-2.2.1+dfsg/package/macosx/script.uninstall000077500000000000000000000013421223036517100213320ustar00rootroot00000000000000#!/bin/sh /bin/launchctl stop net.shrew.iked /bin/launchctl unload /Library/LaunchDaemons/net.shrew.iked.plist /usr/bin/killall "Shrew Soft VPN Client Connect" /usr/bin/killall "Shrew Soft VPN Access Manager" /usr/bin/killall iked /bin/rm -f /etc/iked.conf* /bin/rm -f /Library/LaunchDaemons/net.shrew.iked.plist /bin/rm -f /usr/bin/ikec /bin/rm -f /usr/sbin/iked /bin/rm -f /usr/share/man/man1/ikec.1 /bin/rm -f /usr/share/man/man1/qikea.1 /bin/rm -f /usr/share/man/man1/qikec.1 /bin/rm -f /usr/share/man/man5/iked.conf.5 /bin/rm -f /usr/share/man/man8/iked.8 /bin/rm -f /usr/share/man/man1/ikec.1 /bin/rm -f /usr/sbin/iked /bin/rm -f /usr/sbin/iked /bin/rm -fr /Applications/Shrew\ Soft* /bin/rm -fr /Library/Frameworks/ShrewSoft* ike-2.2.1+dfsg/package/macosx/vpn-client-install.icns000066400000000000000000000745311223036517100225030ustar00rootroot00000000000000icnsyYit329=c !dcddcdcbdcdcdbdcda`! ! ! dcddccddccdccdccdcdcddccdcdcdcbbb!!! ! "ddcdcdcdccdcddcdcdcdcdccdd! ! ! ! ! cdcdccdcdcddccdccddcb]c!dcdcddcdcdcd!ccdcdc! bcdcdeedcdcc! !ccdcdRQ[abcdccd!! dcdcdbqB232237>CEFIOTVWXZ]^_acefedccdc!!dcdchB4665656679;=?ABDFHJMPTVY\_bdgfed!!dbcdcdcb~B4656767799:;;=>?@ABBCHMPRUY^acdcdcd !!dcdcdccpA46 56767799:;:;<=??@ ABCCDCCDEEF EEJNQSTVZ]__`abcd!edcd?5656767799:;:;309=??@ABCCDCDDFFGHGGHIIJK LLNQSTTUWY!! !edcdct?5656767799:;93h5:?@ABCCDCDDFFGHHGHJIJKLKLMNOP! LKMORSVXZ[^_bcbcbf?56,56767799:;WLD??@ABCCDCDDFFGHHGHJIJKLKLMNPPOQP! ! !KJIIKMNOPOr?56,56767783HY<56 567673PBCDDFFGHHGHJIJKLKLMNPPOQPO ! JL If>56565659h~XEBEGHHGHJIJKLKLMNPPOQQO! !!LKL Ie<556556/H⸄N>EHGHJIJKLKLMNPPOQPQ !KKLId5465567]=EHJIJKLKLMNPPOQ !KLJb ܁TNHJKLMNPPOQ! KL KLLMMNLJa [CHKLMNPQ!! ! !!LKLLKLLMNOMD>5.IJ`̀ Ñ7ALMNNP! !!LJA7.% !2L`ľ?OPOP! !";1+# ! !! $B\ Ŀ !  !.YĿ! ! !4Ŀ# ! !Ŀ ! ! !Ŀ! ! Ŀ! ! Ŀ! ! ! Ŀ!! !"" Ŀ ! !  Ľ! !   ! !!""!  ! ! ! "#  ! !  !   !"   !!   M7   *   0410,+-)'('"&# ̀c/99dcddcdcbdcdcdbdcda`8899 dcddccddccdccdccdcdcddccdcdcdcbbb9999798988ddcdcdcdccdcddcdcdcdcdccdd989889898cdcdccdcdcddccdccddcb]c8989dcdcddcdcdcd9ccdcdc98bcdcdeedcdcc988ccdcdRQ[abcdccd8898dcdcdbrC232237>CEFIOTVWXZ]^_acefedcdc9989dcdciB46656789;=?ACDFHJNPTVY\_begfed99dbcdcdcbB4656677899:;;=?@ABBCHNQRUY^acdcdcd8899dcdcdccqA4656677899:;:;;=>=?@@?ACCDDCEF JNRSTVZ^__`abcd98edcd?5656677899:;:;40:=?@@?ACCDEFFGHIJK LLMMOQSTUVWY9989edcdcu?5656677899:;93h5:@@?ACCDEFFGHIJKKLKLMNOPPQ798 MLOPSTVXZ\^`bcbcbf?565667789::;WLC?@AACCDEFFGHIJKKLKLMNOOPOPPRRQR79889LK JLNOPQOs?5656677893IZ<=BCDEFFGHIJKKLKLMNOOPOPPR7889899LMLMMLIm?56 5667792qག7;BDDEFFGHIJKKLKLMNOOPOPPR998999LMJi>56 566774 PBCEFFGHIJKKLKLMNOOPOPPRQP989M Jg>56565659h ~YFBFHIJKKLKLMNOOPOPPRRP8989898M Jf=556556/H㸄O>EHHIJKKLKLMNOOPOPPRQR89MLMJe5465567]=FIJKKLKLMNOOPOPPR998989LMKd܁UNIKLKLMNOOPOPQR88982LMLMKb鷀\DHLMNOOPOPQR789889MLMMLM NNMIFB>KKb΀đ7BMNOPOPQ989899MLHB?;89@La@POOQ8898 9889D@=:778 98998:G] 8979899898>Z989898989D;8988798<9889989( 99899::;8 9894,'  ſ989 87653+%  89 899::943.+'"  99889 899::;40*#! 989895.( 9989 642/,&!9899::;70.'$"9.+"  - \ H &   0    0/10/+-) ('"# ΀c_iidcddcdcbdcdcdbdcda`hhiihhii dcddccddccdccdccdcdcddccdcdcdcbbbhlhhiihhihhddcdcdcdccdcddcdcdcdcdccddkhiihihicdcdccdcdcddccdccddcb]ciihhidcdcddcdcdcdihihiccdcdciihihbcdcdeedcdcchihgccdcdSR[abcdccdfihiadcdcdbsD343348>CEGJPUWWX[]^_`cedcdchihdcdciC5776789:;>@BDEHIKNPTVZ]_begedihiidbcdcdcbC57689:;:<=>?@ABBCD EJORSUZ^acdcdcdhihhidcdcdccqC57689:;:<=>?@?@@ABBCDCDFEFGHHILORTUW[^_``abcdihhedcdA57689:;:<62;??@@ABBCDCDEFFGHGHHJJKLLM NNOPRUVWWYZiihihedcdcvA5768#9:;:<:5i7;@AABBCDCDEFFGHGHHJJKLKLLNPOPPQRRSgih LKMORSVXZ[^_bcbcbfA5768#9:;:?CCDEFFGHGHHJJKLKLLNPOPPRTSSTTghihiiKLKLLKHnA5768:3r྄8=9789 ihicWM@8789ihijjida_YSIA9467889898ihijjklf[WKHB>;67788989 ijiXRD;;:9989:8677898889989989899895H9989*p798578987_98993B988898989898 89899798989989889899889899798989898969 89989899788889948786    " 410,+-) %$"# πt8mk@{¯kP7' %0K\'1'%$#8Huķz^JJHE1_y#ƥtldZ>XgeԺ|6 B#j; j^9GH4uV#XwHYp 2 "B,~l6^EB rl`/EC6LjG֌\Jf3!?iH2P ,, ]_RFe!Xhq ,5y7 n-o!NGhcͭQ-WyC/{L!h<̐ZW0jߴc<(+ ! h P C:4+T< $ h>pF igE+2S"G9 }c9fDDw,L) X6J1sgF@ icnV Bike-2.2.1+dfsg/package/macosx/vpn-client-install.packproj000066400000000000000000002313001223036517100233450ustar00rootroot00000000000000 Hierarchy Attributes Components Attributes Documents Background Image IFPkgFlagBackgroundAlignment 4 IFPkgFlagBackgroundScaling 1 Mode 0 Path Path Type 1 License International Mode 0 Path Path Type 1 ReadMe International Mode 0 Path Path Type 1 Welcome International Mode 0 Path Path Type 1 Files Compress Hierarchy Children Children Children GID 80 Path Utilities Path Type 1 Privileges 509 Type 1 UID 0 GID 80 Path Applications Path Type 1 Privileges 509 Type 1 UID 0 Children Children GID 80 Path Application Support Path Type 1 Privileges 509 Type 1 UID 0 Children GID 80 Path Documentation Path Type 1 Privileges 509 Type 1 UID 0 Children GID 80 Path Filesystems Path Type 1 Privileges 509 Type 1 UID 0 Children Children GID 80 Path /Library/Frameworks/ShrewSoftIdb.framework Path Type 1 Privileges 493 Type 3 UID 0 Children GID 80 Path /Library/Frameworks/ShrewSoftIke.framework Path Type 1 Privileges 493 Type 3 UID 0 Children GID 80 Path /Library/Frameworks/ShrewSoftIp.framework Path Type 1 Privileges 493 Type 3 UID 0 Children GID 80 Path /Library/Frameworks/ShrewSoftIth.framework Path Type 1 Privileges 493 Type 3 UID 0 Children GID 80 Path /Library/Frameworks/ShrewSoftLog.framework Path Type 1 Privileges 493 Type 3 UID 0 Children GID 80 Path /Library/Frameworks/ShrewSoftPfkey.framework Path Type 1 Privileges 493 Type 3 UID 0 GID 80 Path Frameworks Path Type 1 Privileges 509 Type 1 UID 0 Children GID 80 Path Internet Plug-ins Path Type 1 Privileges 509 Type 1 UID 0 Children GID 80 Path PreferencePanes Path Type 1 Privileges 509 Type 1 UID 0 Children GID 80 Path Printers Path Type 1 Privileges 509 Type 1 UID 0 Children GID 80 Path QuickTime Path Type 1 Privileges 509 Type 1 UID 0 Children GID 80 Path Screen Savers Path Type 1 Privileges 509 Type 1 UID 0 Children GID 80 Path Scripts Path Type 1 Privileges 509 Type 1 UID 0 GID 80 Path Library Path Type 1 Privileges 1021 Type 1 UID 0 Children Children Children GID 0 Path Extensions Path Type 1 Privileges 493 Type 1 UID 0 GID 0 Path Library Path Type 1 Privileges 493 Type 1 UID 0 GID 0 Path System Path Type 1 Privileges 493 Type 1 UID 0 GID 80 Path / Path Type 1 Privileges 1021 Type 1 UID 0 IFPkgFlagDefaultLocation /Library/Frameworks Imported Package Package Path Split Forks Plugins PluginsList Path Introduction Type 0 Path ReadMe Type 0 Path License Type 0 Path Target Type 0 Path PackageSelection Type 0 Path Install Type 0 Path FinishUp Type 0 Scripts Additional Resources International Installation Scripts IFInstallationScriptsPostflight Path Status IFInstallationScriptsPostinstall Path Status IFInstallationScriptsPostupgrade Path Status IFInstallationScriptsPreflight Path Status IFInstallationScriptsPreinstall Path Status IFInstallationScriptsPreupgrade Path Status Requirements Settings Description International IFPkgDescriptionDeleteWarning IFPkgDescriptionDescription This package contains the Shrew Soft VPN Client libraries. IFPkgDescriptionTitle Library Frameworks IFPkgDescriptionVersion 2.2.0 Display Information CFBundleGetInfoString Shrew Soft VPN Client Copyright © 2010 Shrew Soft Inc CFBundleIconFile CFBundleIconFile Path Type 1 CFBundleIdentifier net.shrew.pkg.vpn.frameworks CFBundleName Library Frameworks CFBundleShortVersionString 2.2.0 Options IFPkgFlagAllowBackRev IFPkgFlagAuthorizationAction 1 IFPkgFlagFollowLinks IFPkgFlagIsRequired IFPkgFlagOverwritePermissions IFPkgFlagRelocatable IFPkgFlagRestartAction 0 IFPkgFlagRootVolumeOnly IFPkgFlagUpdateInstalledLanguages Version IFMajorVersion 2 IFMinorVersion 2 IFPkgFlagPackageSelection 1 Name Library Frameworks Status 1 Type 1 Attributes Documents Background Image IFPkgFlagBackgroundAlignment 4 IFPkgFlagBackgroundScaling 1 Mode 0 Path Path Type 1 License International Mode 0 Path Path Type 1 ReadMe International Mode 0 Path Path Type 1 Welcome International Mode 0 Path Path Type 1 Files Compress Hierarchy Children Children Children GID 80 Path Utilities Path Type 1 Privileges 509 Type 1 UID 0 GID 80 Path Applications Path Type 1 Privileges 509 Type 1 UID 0 Children Children GID 80 Path ../../source/iked/iked.conf.sample Path Type 2 Privileges 420 Type 3 UID 0 GID 80 Path etc Path Type 1 Privileges 509 Type 2 UID 0 Children Children GID 80 Path Application Support Path Type 1 Privileges 509 Type 1 UID 0 Children GID 80 Path Documentation Path Type 1 Privileges 509 Type 1 UID 0 Children GID 80 Path Filesystems Path Type 1 Privileges 509 Type 1 UID 0 Children GID 80 Path Frameworks Path Type 1 Privileges 509 Type 1 UID 0 Children GID 80 Path Internet Plug-ins Path Type 1 Privileges 509 Type 1 UID 0 Children Children GID 80 Path ../../script/macosx/net.shrew.iked.plist Path Type 2 Privileges 420 Type 3 UID 0 GID 80 Path LaunchDaemons Path Type 1 Privileges 509 Type 2 UID 0 Children GID 80 Path PreferencePanes Path Type 1 Privileges 509 Type 1 UID 0 Children GID 80 Path Printers Path Type 1 Privileges 509 Type 1 UID 0 Children GID 80 Path QuickTime Path Type 1 Privileges 509 Type 1 UID 0 Children GID 80 Path Screen Savers Path Type 1 Privileges 509 Type 1 UID 0 Children GID 80 Path Scripts Path Type 1 Privileges 509 Type 1 UID 0 GID 80 Path Library Path Type 1 Privileges 1021 Type 1 UID 0 Children Children Children GID 0 Path Extensions Path Type 1 Privileges 493 Type 1 UID 0 GID 0 Path Library Path Type 1 Privileges 493 Type 1 UID 0 GID 0 Path System Path Type 1 Privileges 493 Type 1 UID 0 Children Children Children GID 80 Path /usr/sbin/iked Path Type 1 Privileges 493 Type 3 UID 0 GID 80 Path sbin Path Type 1 Privileges 509 Type 2 UID 0 Children Children Children Children GID 80 Path ../../source/iked/iked.conf.5 Path Type 2 Privileges 420 Type 3 UID 0 GID 80 Path man5 Path Type 1 Privileges 509 Type 2 UID 0 Children Children GID 80 Path ../../source/iked/iked.8 Path Type 2 Privileges 420 Type 3 UID 0 GID 80 Path man8 Path Type 1 Privileges 509 Type 2 UID 0 GID 80 Path man Path Type 1 Privileges 509 Type 2 UID 0 GID 80 Path share Path Type 1 Privileges 509 Type 2 UID 0 GID 80 Path usr Path Type 1 Privileges 509 Type 2 UID 0 GID 80 Path / Path Type 1 Privileges 1021 Type 1 UID 0 IFPkgFlagDefaultLocation / Imported Package Package Path Split Forks Plugins PluginsList Path Introduction Type 0 Path ReadMe Type 0 Path License Type 0 Path Target Type 0 Path PackageSelection Type 0 Path Install Type 0 Path FinishUp Type 0 Scripts Additional Resources International Installation Scripts IFInstallationScriptsPostflight Path Status IFInstallationScriptsPostinstall Path Status IFInstallationScriptsPostupgrade Path Status IFInstallationScriptsPreflight Path Status IFInstallationScriptsPreinstall Path Status IFInstallationScriptsPreupgrade Path Status Requirements Settings Description International IFPkgDescriptionDeleteWarning IFPkgDescriptionDescription This package contains the Shrew Soft Internet Key Exchange protocol daemon. It enables this software to communicate with IPsec VPN gateways. IFPkgDescriptionTitle IKE Daemon IFPkgDescriptionVersion 2.2.0 Display Information CFBundleGetInfoString Shrew Soft VPN Client Copyright © 2010 Shrew Soft Inc CFBundleIconFile CFBundleIconFile Path Type 1 CFBundleIdentifier net.shrew.pkg.vpn.iked CFBundleName IKE Daemon CFBundleShortVersionString 2.2.0 Options IFPkgFlagAllowBackRev IFPkgFlagAuthorizationAction 1 IFPkgFlagFollowLinks IFPkgFlagIsRequired IFPkgFlagOverwritePermissions IFPkgFlagRelocatable IFPkgFlagRestartAction 0 IFPkgFlagRootVolumeOnly IFPkgFlagUpdateInstalledLanguages Version IFMajorVersion 2 IFMinorVersion 2 IFPkgFlagPackageSelection 1 Name IKE Daemon Status 1 Type 1 Attributes Documents Background Image IFPkgFlagBackgroundAlignment 4 IFPkgFlagBackgroundScaling 1 Mode 0 Path Path Type 1 License International Mode 0 Path Path Type 1 ReadMe International Mode 0 Path Path Type 1 Welcome International Mode 0 Path Path Type 1 Files Compress Hierarchy Children Children Children GID 80 Path Utilities Path Type 1 Privileges 509 Type 1 UID 0 GID 80 Path Applications Path Type 1 Privileges 509 Type 1 UID 0 Children Children GID 80 Path Application Support Path Type 1 Privileges 509 Type 1 UID 0 Children GID 80 Path Documentation Path Type 1 Privileges 509 Type 1 UID 0 Children GID 80 Path Filesystems Path Type 1 Privileges 509 Type 1 UID 0 Children GID 80 Path Frameworks Path Type 1 Privileges 509 Type 1 UID 0 Children GID 80 Path Internet Plug-ins Path Type 1 Privileges 509 Type 1 UID 0 Children GID 80 Path PreferencePanes Path Type 1 Privileges 509 Type 1 UID 0 Children GID 80 Path Printers Path Type 1 Privileges 509 Type 1 UID 0 Children GID 80 Path QuickTime Path Type 1 Privileges 509 Type 1 UID 0 Children GID 80 Path Screen Savers Path Type 1 Privileges 509 Type 1 UID 0 Children GID 80 Path Scripts Path Type 1 Privileges 509 Type 1 UID 0 GID 80 Path Library Path Type 1 Privileges 1021 Type 1 UID 0 Children Children Children GID 0 Path Extensions Path Type 1 Privileges 493 Type 1 UID 0 GID 0 Path Library Path Type 1 Privileges 493 Type 1 UID 0 GID 0 Path System Path Type 1 Privileges 493 Type 1 UID 0 Children Children Children GID 80 Path /usr/bin/ikec Path Type 1 Privileges 493 Type 3 UID 0 GID 80 Path bin Path Type 1 Privileges 509 Type 2 UID 0 Children Children Children GID 80 Path ../../source/ikec/ikec.1 Path Type 2 Privileges 420 Type 3 UID 0 GID 80 Path man1 Path Type 1 Privileges 509 Type 2 UID 0 GID 80 Path man Path Type 1 Privileges 509 Type 2 UID 0 GID 80 Path usr Path Type 1 Privileges 509 Type 2 UID 0 GID 80 Path / Path Type 1 Privileges 1021 Type 1 UID 0 IFPkgFlagDefaultLocation / Imported Package Package Path Split Forks Plugins PluginsList Path Introduction Type 0 Path ReadMe Type 0 Path License Type 0 Path Target Type 0 Path PackageSelection Type 0 Path Install Type 0 Path FinishUp Type 0 Scripts Additional Resources International Installation Scripts IFInstallationScriptsPostflight Path Status IFInstallationScriptsPostinstall Path Status IFInstallationScriptsPostupgrade Path Status IFInstallationScriptsPreflight Path Status IFInstallationScriptsPreinstall Path Status IFInstallationScriptsPreupgrade Path Status Requirements Settings Description International IFPkgDescriptionDeleteWarning IFPkgDescriptionDescription This package contains the Shrew Soft CLI client applications. They enable users to control IPsec VPN connections from a terminal window. IFPkgDescriptionTitle CLI Applications IFPkgDescriptionVersion 2.2.0 Display Information CFBundleGetInfoString Shrew Soft VPN Client Copyright © 2010 Shrew Soft Inc CFBundleIconFile CFBundleIconFile Path Type 1 CFBundleIdentifier net.shrew.pkg.vpn.cli CFBundleName CLI Applications CFBundleShortVersionString 2.2.0 Options IFPkgFlagAllowBackRev IFPkgFlagAuthorizationAction 1 IFPkgFlagFollowLinks IFPkgFlagIsRequired IFPkgFlagOverwritePermissions IFPkgFlagRelocatable IFPkgFlagRestartAction 0 IFPkgFlagRootVolumeOnly IFPkgFlagUpdateInstalledLanguages Version IFMajorVersion 2 IFMinorVersion 2 IFPkgFlagPackageSelection 0 Name CLI Applications Status 1 Type 1 Attributes Documents Background Image IFPkgFlagBackgroundAlignment 4 IFPkgFlagBackgroundScaling 1 Mode 0 Path Path Type 1 License International Mode 0 Path Path Type 1 ReadMe International Mode 0 Path Path Type 1 Welcome International Mode 0 Path Path Type 1 Files Compress Hierarchy Children Children Children GID 80 Path /Applications/Shrew Soft VPN Access Manager.app Path Type 1 Privileges 493 Type 3 UID 0 Children GID 80 Path /Applications/Shrew Soft VPN Client Connect.app Path Type 1 Privileges 493 Type 3 UID 0 Children GID 80 Path Utilities Path Type 1 Privileges 509 Type 1 UID 0 GID 80 Path Applications Path Type 1 Privileges 509 Type 1 UID 0 Children Children GID 80 Path Application Support Path Type 1 Privileges 509 Type 1 UID 0 Children GID 80 Path Documentation Path Type 1 Privileges 509 Type 1 UID 0 Children GID 80 Path Filesystems Path Type 1 Privileges 509 Type 1 UID 0 Children Children GID 80 Path /Library/Frameworks/ShrewSoftQtCore.framework Path Type 1 Privileges 493 Type 3 UID 0 Children GID 80 Path /Library/Frameworks/ShrewSoftQtGui.framework Path Type 1 Privileges 493 Type 3 UID 0 GID 80 Path Frameworks Path Type 1 Privileges 509 Type 1 UID 0 Children GID 80 Path Internet Plug-ins Path Type 1 Privileges 509 Type 1 UID 0 Children GID 80 Path PreferencePanes Path Type 1 Privileges 509 Type 1 UID 0 Children GID 80 Path Printers Path Type 1 Privileges 509 Type 1 UID 0 Children GID 80 Path QuickTime Path Type 1 Privileges 509 Type 1 UID 0 Children GID 80 Path Screen Savers Path Type 1 Privileges 509 Type 1 UID 0 Children GID 80 Path Scripts Path Type 1 Privileges 509 Type 1 UID 0 GID 80 Path Library Path Type 1 Privileges 1021 Type 1 UID 0 Children Children Children GID 0 Path Extensions Path Type 1 Privileges 493 Type 1 UID 0 GID 0 Path Library Path Type 1 Privileges 493 Type 1 UID 0 GID 0 Path System Path Type 1 Privileges 493 Type 1 UID 0 GID 80 Path / Path Type 1 Privileges 1021 Type 1 UID 0 IFPkgFlagDefaultLocation / Imported Package Package Path Split Forks Plugins PluginsList Path Introduction Type 0 Path ReadMe Type 0 Path License Type 0 Path Target Type 0 Path PackageSelection Type 0 Path Install Type 0 Path FinishUp Type 0 Scripts Additional Resources International Installation Scripts IFInstallationScriptsPostflight Path Status IFInstallationScriptsPostinstall Path Status IFInstallationScriptsPostupgrade Path Status IFInstallationScriptsPreflight Path Status IFInstallationScriptsPreinstall Path Status IFInstallationScriptsPreupgrade Path Status Requirements Settings Description International IFPkgDescriptionDeleteWarning IFPkgDescriptionDescription This package contains the Shrew Soft GUI client applications. They enable users to create Site Configurations and control IPsec VPN connections from a graphical user interface. IFPkgDescriptionTitle GUI Applications IFPkgDescriptionVersion 2.2.0 Display Information CFBundleGetInfoString CFBundleIconFile CFBundleIconFile Path Type 1 CFBundleIdentifier net.shrew.pkg.vpn.gui CFBundleName GUI Applications CFBundleShortVersionString 2.2.0 Options IFPkgFlagAllowBackRev IFPkgFlagAuthorizationAction 1 IFPkgFlagFollowLinks IFPkgFlagIsRequired IFPkgFlagOverwritePermissions IFPkgFlagRelocatable IFPkgFlagRestartAction 0 IFPkgFlagRootVolumeOnly IFPkgFlagUpdateInstalledLanguages Version IFMajorVersion 2 IFMinorVersion 2 IFPkgFlagPackageSelection 0 Name GUI Applications Status 1 Type 1 Documents Background Image IFPkgFlagBackgroundAlignment 4 IFPkgFlagBackgroundScaling 1 Mode 0 Path Path Type 1 License International Mode 0 Path ../../../LICENSE.TXT Path Type 2 ReadMe International Mode 0 Path Path Type 1 Welcome International Mode 0 Path Path Type 1 Plugins PluginsList Path Introduction Type 0 Path ReadMe Type 0 Path License Type 0 Path Target Type 0 Path PackageSelection Type 0 Path Install Type 0 Path FinishUp Type 0 Scripts Additional Resources International Installation Scripts IFInstallationScriptsPostflight Path Status IFInstallationScriptsPostinstall Path script.postinstall Path Type 2 Status IFInstallationScriptsPostupgrade Path script.postinstall Path Type 2 Status IFInstallationScriptsPreflight Path Status IFInstallationScriptsPreinstall Path Status IFInstallationScriptsPreupgrade Path Status Requirements Settings Description International IFPkgDescriptionDeleteWarning IFPkgDescriptionDescription IFPkgDescriptionTitle Shrew Soft VPN Client Install IFPkgDescriptionVersion 2.2.0 Display Information CFBundleGetInfoString Shrew Soft VPN Client Copyright © 2010 Shrew Soft Inc CFBundleIconFile vpn-client-install.icns CFBundleIconFile Path Type 2 CFBundleIdentifier net.shrew.pkg.vpn-client-install CFBundleName Shrew Soft VPN Client Install CFBundleShortVersionString 2.2.0 Version IFMajorVersion 2 IFMinorVersion 2 IFPkgFlagComponentDirectory Contents/Resources IFPkgFlagPackageSelection 0 Name Shrew Soft VPN Client Status 1 Type 0 Name Project Settings 10.1 Compatibility Build Path build Build Path Type 2 Comment Remove .DS_Store Remove .pbdevelopment ike-2.2.1+dfsg/package/macosx/vpn-client-volume.icns000066400000000000000000001026621223036517100223410ustar00rootroot00000000000000icnsit32EZknqsqovt|~~uq^PnqH)k̀΀πЂрӀԀՁր؀ـڃہ݁ރ߇ʼxH\ր؀ـځہ݁ހ߄˺l7Ho܀څۂ܀݂ނ߅DZQN`\άnkϹ~7hѻK7fҼU 7gԿRBl‘T@rřZ Hyƞb M~ȣf P ´׆cipwʩkV ͢wdS>-!4薉dcedegnpt~̯qY,"!.kdcdcdccdeedg iilpqsxz|~͈ͳv7 ]4!"X}db^effededcdjϷ{P 7d ) ҿV Bvd ?VG}z!x Ę`P%%Rk ŞbUI 3XyȥfV`4Ma|ʩk[ y !.8Ix˯qaNAgͳu) fϸ}H )mѺPHrҾVBxVG~×ZTŜa WîǣfY ˭ɨi\ѱˬodٲ̱t7g 㷫ε{> 7m켫йI >sѽUGzӿPMƭ”ZPղĚ\V⵫šdY𶬮Ȧg\ʫmdմ̱p0i޾͵yB0mŹиIBsƽѺGI{ ҾTG ZTØZV ş`Zǥc\ʩjc˯o!hͲw7 !m϶|@ 5tѹG@zҽNGӿP NXQŻZT̀σІуӃԄՈօׂ؈ّȿa Zาf kֿw pɵ iη6 gѻ2 +oҿ<1z›A 6ŢL>ǨVF˭bQѳk`ջvqہۄ{ققÊ{ٍٍÅqуדذٓ؃ѸohֆϸőυͰeWՅϨzj^jzτˬ[QՅ{^{˨VAփk^kɤK:Ӆ`^`ǟE)҅ojnruwxvspkpŚ6хzʋ|ĕ0ЅϪÔτŽ!lՅйˑЅмzA։׆ȢHs̀ֈׂրηvz҆փ׆̵$c͏ϏЧψ΂ȻhUv}W" Zknqsqovt|~~uq^PnqH)k̀΀ςЀрӀԀՁր؀ـڃہ݁ކ߄ʼxH\ր؀ـځہ݁ނ߂˺l7Ho܀څۂ܀݂ޅ߂DZQN`\άnkϹ~7hлK7fҼU 7gԿRBlT@rřZ Hyƞb M~ȣf P Ȼ׆cipwʩkV ҬtfRD9J薉dcedegnpt~̯qY C:889899Ekdcdcdccdeedg iilpqsxz|~͈ͳv7 ]I9:j}db^effededcdjϷ{P 7dQ9Vфcdcec<;<@DFKNQTX[^``aabccddededѻU7gU9Gjcd$mm6334679;=??>CHHKMPQTVWZ[\^^_aabcdv҇ҾRBnT9=vxffe&dh{r76655677:23>6/:ABDEGHJKLNQRSVVXZ[_TDsa89ZҀ2zZ[\]^_``bpq76656787/CiD5=ABDEFFGHJKLNOOQR[Õ\Ly|>97H_MNNPQSTSYtp7665663:W֜tZHB@CFGHJJKLNOOPSnŜ^ N@9:ssMLKKIOpq9623EpmVJDCGJKKLNOOPRǡcP=9UׁSMLQnh^SODTٱ^LGFIKLNOOPQʨjU=9EWMLPmޱqGDJKNOOPlˬm ZK9_ZLMLPmޙVFLOOP̲t^^9O[KJFC@; 7mйI >sѽUGz­ӿPMǯ”ZPֳĚ\VⷭšdY𸮰Ȧg\ʫmdֶ̰p0i޿͵yB0mƺиIBsȾѺGI{ ҾTG ZT ØZV ş`Zǥc\ʩjc˯o!hͲw7 !m϶|@ 5tйG@zҽNGӿP NXQŻZT̀χЂуӃԄՈօׂ؈ّȿa Z߸f kֿw pɵ iη6 gл2 +oҿ<1z›A 6ŢL>ǨVF˭bQѳk`ջvqہۄ{ققÊzٍٍÄpуדذٓ؃ѸohֆϸőυͰcWՅϨzj^jzτˬ[QՅ{^{˨VAփk^kɤJ7Ӆ`^`ǟE)҅ojnruwxvspkpŚ6хzʋ|Ĕ0ЅϪÔτ!kՅйɑЅмyA։׆ȡHs̀ֈׂրηvy҆փ׆̵$b͏ϏЧψ΂ȻgRv|W" Zknqsqovt|~~uq^PnqH)k̀΀πЂрӀԀՁր؀ـڃہ݁ރ߇ʼxH\ր؀ـځہ݁ހ߄˺l7Ho܀څۂ܀݂ނ߅DZQN`\άnkϹ~7hѻK7fҼU 7gԿRBl‘T@rřZ Hyƞb M~ȣf P ׆cipwʩkV ۾|qiu薉dcedegnpt~̯qYpiqkdcdcdccdeedg iilpqsxz|~͈ͳv7 ]uij}da^effededcdjϷ{P 7d{i~ۄcdced=<=@DGKORUX[^``abcbcddededѻU7g~isjcd cdmo744568:<>@DHILNQRUVXZ[]^_`abbcdv҇ҾRBn|ilxfedh}t876788;46@7/;BCDFHJKMNOQSTVXYZ\`TDshi܀yY[\]^^_`bqs8768980DiE6>ADFGGHIJKLNOPRSU]Õ\Lylit^LMNOQQRSXtr8764;X֜u[HDBEHIJLNOPQRUpŜ^ NnijsLKJHOqs:734FqnWLEDILNOPQRTǡcPli~SLKPoh^SPDUٱ_MIIJLNOPQRSʨjUlirVLJPn޲rIFKMOPQRmˬm ZwiYLKJPnޚWHMPQR̲t^ⅇiz\NPTX]dbVqЂ íϷyBc撇ilµedfghhiie йH Bhhipyvpikjiin żѽN 7oihik ƿW Dtkix ƾ”X L{pijigh ś[Osi jijiihhfc_ZUZӁƠdPwij d[TMGB@=:EʁȧgX؈ihijjkljcXOH?<<;:98G˂˪lZjjihge\UME?=<::88989Ǵ ̱s`]WRKGB?=;7667889H ʹx)e D@<96456889H и~H )j=678896A ѼP 7pe9 879T ҿV Bv988 7mйI >s°ѽUGzİӿPMɲ”ZP׶Ě\V㹰šdY𻱳Ȧg\°ʫmd׸̱p0i¸͵yB0mɼиIBsѺGI{ ҾTG ZT ØZV ş`Zǥc\ʩjc˯o!hͲw7 !m϶|@ 5tѹG@zҽNGӿP NXQŻZT̀σІуӃԄՈօׂ؈ّȿa Zาf kֿw pɵ iη6 gѻ2 +oҿ<1z›A 6ŢL>ǨVF˭bQѳk`ջvqہۄ{ققÊvٍٍÀlуדذٓ؃ѸmaֆϸőυͰaRՅϨzj^jzτ˫XMՅ{^{˨R>փk^kɣH4Ӆ`^`ǞB)҅ojnruwxvspkpŘ6хzʋ|Ē0~ЅϪÔτ‹!hՅйˑЅмv;։׆ȠEǹֈׂրηrt҆փ׆̴{! ^͏ϏЧψ΂ȺcNqwT  t8mk@*.---....//////////////.................../////////////////////............----..-, 5֪F kY}7Fpn  .?-S?hTh  .:+P:bP~b~  ,:+P9aPa~)4)L4]Lz]z)4)M2XItYt&4&J4YKtYt%2%F2XGsXt  )6)L6ZGp\q  5G0eJ} a  ~  #/ %       e  [  Io  ?a  4P  )6  %z)  "@R& 0[n5" +?euD0 &7I^ƐeN;)  .>N\itvk_RB1" %3AMYahlnpppqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpppomic[QD7(  &2=GOVY\^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\ZVRI@5*  &/7>CGIJLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLKJGD@91(  #)/368:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::8640+%  !%&()))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))(&%"     icnV Bike-2.2.1+dfsg/script/000077500000000000000000000000001223036517100145075ustar00rootroot00000000000000ike-2.2.1+dfsg/script/linux/000077500000000000000000000000001223036517100156465ustar00rootroot00000000000000ike-2.2.1+dfsg/script/linux/iked000077500000000000000000000015301223036517100165070ustar00rootroot00000000000000#! /bin/sh set -e # /etc/init.d/iked: start and stop the Shrew Soft IKE daemon test -x /usr/sbin/iked || exit 0 . /lib/lsb/init-functions export PATH="${PATH:+$PATH:}/usr/sbin:/sbin" case "$1" in start) log_begin_msg "Starting Shrew Soft IKE daemon..." start-stop-daemon --start --quiet --exec /usr/sbin/iked || log_end_msg 1 log_end_msg 0 ;; stop) log_begin_msg "Stopping Shrew Soft IKE daemon..." start-stop-daemon --stop --quiet --oknodo --exec /usr/sbin/iked || log_end_msg 1 log_end_msg 0 ;; restart) log_begin_msg "Restarting Shrew Soft IKE daemon..." start-stop-daemon --stop --quiet --oknodo --retry 30 --exec /usr/sbin/iked || log_end_msg 1 start-stop-daemon --start --quiet --exec /usr/sbin/iked || log_end_msg 1 log_end_msg 0 ;; *) log_success_msg "Usage: /etc/init.d/iked {start|stop|restart}" exit 1 esac exit 0 ike-2.2.1+dfsg/script/macosx/000077500000000000000000000000001223036517100160015ustar00rootroot00000000000000ike-2.2.1+dfsg/script/macosx/net.shrew.iked.plist000066400000000000000000000013311223036517100217040ustar00rootroot00000000000000 Label net.shrew.iked ProgramArguments /usr/sbin/iked -F RunAtLoad KeepAlive UserName root Sockets Listeners SockFamily Unix SockPathMode 755 SockPathName /var/run/ikedi ike-2.2.1+dfsg/source/000077500000000000000000000000001223036517100145035ustar00rootroot00000000000000ike-2.2.1+dfsg/source/compat/000077500000000000000000000000001223036517100157665ustar00rootroot00000000000000ike-2.2.1+dfsg/source/compat/inttypes.h000066400000000000000000000060651223036517100200250ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #ifndef _INTTYPES_H_ #define _INTTYPES_H_ typedef unsigned char u_char; typedef __int8 int8; typedef __int16 int16; typedef __int32 int32; typedef __int64 int64; typedef unsigned __int8 uint8; typedef unsigned __int16 uint16; typedef unsigned __int32 uint32; typedef unsigned __int64 uint64; typedef __int8 int8_t; typedef __int16 int16_t; typedef __int32 int32_t; typedef __int64 int64_t; typedef unsigned __int8 uint8_t; typedef unsigned __int16 uint16_t; typedef unsigned __int32 uint32_t; typedef unsigned __int64 uint64_t; typedef int8_t __int8_t; typedef int16_t __int16_t; typedef int32_t __int32_t; typedef int64_t __int64_t; typedef uint8_t __uint8_t; typedef uint16_t __uint16_t; typedef uint32_t __uint32_t; typedef uint64_t __uint64_t; typedef uint8_t u_int8_t; typedef uint16_t u_int16_t; typedef uint32_t u_int32_t; typedef uint64_t u_int64_t; #endif ike-2.2.1+dfsg/source/compat/tun_ioctls.h000066400000000000000000000035431223036517100203270ustar00rootroot00000000000000/* * ip tunnel device for MacOSX. */ /* * Copyright (c) 2004, 2005, 2006, 2007, 2008, 2009 Mattias Nissler * * Redistribution and use in source and binary forms, with or without modification, are permitted * provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials provided * with the distribution. * 3. The name of the author may not be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. */ #ifndef __TUN_IOCTLS_H__ #define __TUN_IOCTLS_H__ /* Tun supports prepending a four byte address family field to each packet. These ioctls allow you * to switch it on/off. Pass 1 as parameter to switch it on, pass 0 for off. */ #define TUNSIFHEAD _IOW('t', 96, int) #define TUNGIFHEAD _IOR('t', 97, int) #endif /* __TUN_IOCTLS_H__ */ ike-2.2.1+dfsg/source/compat/winstring.h000066400000000000000000000061001223036517100201600ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ // // UNIX compatibiliy for MS string functions // #ifndef _WINSTRING_H_ #define _WINSTRING_H_ #include #include #include inline int vsprintf_s( char * buffer, size_t numberOfElements, const char * format, va_list argptr ) { return vsnprintf( buffer, numberOfElements, format, argptr ); } inline int sprintf_s( char * buffer, size_t sizeOfBuffer, const char * format, ... ) { va_list list; va_start( list, format ); return vsnprintf( buffer, sizeOfBuffer, format, list ); } inline int strcpy_s( char * strDestination, size_t sizeInBytes, const char * strSource ) { strncpy( strDestination, strSource, sizeInBytes ); return 0; } inline int strncpy_s( char * strDestination, const char * strSource, size_t sizeInBytes ) { strncpy( strDestination, strSource, sizeInBytes ); return 0; } inline int _stricmp( const char * str1, const char * str2 ) { return strcasecmp( str1, str2 ); } #endif ike-2.2.1+dfsg/source/export.h000066400000000000000000000042651223036517100162040ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #ifdef WIN32 #define DLX __declspec( dllexport ) #else #define DLX #endif ike-2.2.1+dfsg/source/ikec/000077500000000000000000000000001223036517100154165ustar00rootroot00000000000000ike-2.2.1+dfsg/source/ikec/CMakeLists.txt000066400000000000000000000014241223036517100201570ustar00rootroot00000000000000# # Shrew Soft VPN / Client Connect Application # Cross Platform Make File # # author : Matthew Grooms # : mgrooms@shrew.net # : Copyright 2007, Shrew Soft Inc # include_directories( ${IKE_SOURCE_DIR}/source/ ${IKE_SOURCE_DIR}/source/ikea ${IKE_SOURCE_DIR}/source/iked ${IKE_SOURCE_DIR}/source/libike ${IKE_SOURCE_DIR}/source/libidb ${IKE_SOURCE_DIR}/source/libith ${IKE_SOURCE_DIR}/source/liblog ${IKE_SOURCE_DIR}/source/libip ${QT_INCLUDES} ) link_directories( ${IKE_SOURCE_DIR}/source/libip ) add_executable( ikec main.cpp ikec.cpp ) target_link_libraries( ikec ss_ike ss_idb ss_ith ss_log crypto pthread edit ) # install support install( TARGETS ikec RUNTIME DESTINATION ${PATH_BIN} ) install( FILES ikec.1 DESTINATION ${PATH_MAN}/man1 ) ike-2.2.1+dfsg/source/ikec/ikec.1000066400000000000000000000071021223036517100164130ustar00rootroot00000000000000.\" .\" Copyright (c) 2007 .\" Shrew Soft Inc. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" 3. Redistributions in any form must be accompanied by information on .\" how to obtain complete source code for the software and any .\" accompanying software that uses the software. The source code .\" must either be included in the distribution or be available for no .\" more than the cost of distribution plus a nominal fee, and must be .\" freely redistributable under reasonable conditions. For an .\" executable file, complete source code means the source code for all .\" modules it contains. It does not include source code for modules or .\" files that typically accompany the major components of the operating .\" system on which the executable file runs. .\" .\" THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS .\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED .\" WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR .\" NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC .\" 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. .\" .\" AUTHOR : Matthew Grooms .\" mgrooms@shrew.net .\" .\" .Dd Febuary 2, 2007 .Dt IKEC 1 .Os .Sh NAME .Nm ikec .Nd Internet Key Exchange Connect .Sh SYNOPSIS .Nm .Op Fl r Ar name .Op Fl u Ar username .Op Fl p Ar password .Op Fl a .Sh DESCRIPTION The .Nm command line application provides a simple interface for users to interact with .Xr iked 8 ( Shrew Soft IKE Daemon ). This interface allows a user to control an IPsec VPN Client connection with a remote gateway. The parameters used for the connection are described in a Site Configuration file ( see below ). .Pp The options are as follows: .Bl -tag -width Fl .It Fl r Ar name Specify the Site Configuration name. .It Fl u Ar username Specify the Xauth username for the connection. .It Fl p Ar password Specify the Xauth password for the connection. .It Fl a Automatically initiate the connection. .El .Sh RETURN VALUES The command exits with 0 on success, and non-zero on errors. .Sh FILES All user related configuration data is stored under the .Pa ~/.iked directory. Site Configuration files are stored under the .Pa ~/.iked/sites directory. Certificates and keys are are typically stored under the .Pa ~/.iked/certs directory. These directories are automatically created when the .Nm application is run for the first time by a user. .Sh SITE CONFIGRUATIONS TODO : copy info from readme. .Sh SEE ALSO .Xr iked 8 , .Xr ikec-qt 1 , .Xr ikea-qt 1 , .Sh HISTORY The .Nm program was written by Matthew Grooms ( mgrooms@shrew.net ) as part of the Shrew Soft ( http://www.shrew.net ) family of IPsec products. ike-2.2.1+dfsg/source/ikec/ikec.cpp000066400000000000000000000150131223036517100170350ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "ikec.h" const char * prompt( EditLine * e ) { return "<< : enter xauth username : "; } const char * _IKEC::app_name() { static const char name[] = "ikec"; return name; } bool _IKEC::get_username() { if( !auto_connect() ) read_str( username ); return true; } bool _IKEC::get_password() { if( !auto_connect() ) read_pwd( password, "<< : enter xauth password : " ); return true; } bool _IKEC::get_filepass( BDATA & path ) { // null terminate path path.add( "", 1 ); log( 0, "file password required for %s\n", path.text() ); read_pwd( fpass, "<< : enter file password : " ); return true; } bool _IKEC::set_stats() { return true; } bool _IKEC::set_status( long status, BDATA * text ) { switch( status ) { case STATUS_DISCONNECTED: log( status, "tunnel disabled\n" ); break; case STATUS_CONNECTING: log( status, "bringing up tunnel ...\n" ); break; case STATUS_CONNECTED: log( status, "tunnel enabled\n" ); break; case STATUS_DISCONNECTING: log( status, "bringing down tunnel\n" ); break; case STATUS_BANNER: if( text != NULL ) log( status, "login banner \n\n%s\n", text->text() ); break; default: if( text != NULL ) log( status, "%s", text->text() ); } return true; } _IKEC::_IKEC() { // init line editor el = el_init( "ikec", stdin, stdout, stderr ); el_set( el, EL_EDITOR, "emacs" ); el_set( el, EL_PROMPT, &prompt ); } _IKEC::~_IKEC() { // free line editor el_end( el ); } bool _IKEC::log( long code, const char * format, ... ) { switch( code ) { case STATUS_INFO: printf( "%s", ">> : " ); break; case STATUS_WARN: printf( "%s", "ww : " ); break; case STATUS_FAIL: printf( "%s", "!! : " ); break; default: printf( "%s", "ii : " ); break; } va_list list; va_start( list, format ); vprintf( format, list ); return true; } bool _IKEC::read_key( char & value ) { return el_getc( el, &value ) != -1; } bool _IKEC::read_str( BDATA & value ) { int size = 0; const char * line; while( size < 1 ) { line = el_gets( el, &size ); if( line == NULL ) return false; } value.del(); value.set( line, --size ); return true; } bool _IKEC::read_pwd( BDATA & value, const char * prompt ) { // // using libedit to accept password // input is maddening. there is no // way to disable echo // const char * line = getpass( prompt ); printf( "%s", "\n" ); value.del(); value.set( line, strlen( line ) ); return true; } void _IKEC::show_stats() { static char state_disconnected[] = "disconnected"; static char state_connecting[] = "connecting"; static char state_connected[] = "connected"; static char state_disconnecting[] = "disconnecting"; static char xport_ike_esp[] = "IKE | ESP"; static char xport_ike_natt_cisco[] = "IKE | CISCO-UDP / ESP"; static char xport_ike_natt_v00[] = "NAT-T v00 / IKE | ESP"; static char xport_ike_natt_v01[] = "NAT-T v01 / IKE | ESP"; static char xport_ike_natt_v02[] = "NAT-T v02 / IKE | ESP"; static char xport_ike_natt_v03[] = "NAT-T v03 / IKE | ESP"; static char xport_ike_natt_rfc[] = "NAT-T RFC / IKE | ESP"; static char enabled[] = "enabled"; static char disabled[] = "disabled"; char * state; char * xport; char * frag; char * dpd; switch( cstate ) { case CLIENT_STATE_DISCONNECTED: state = state_disconnected; break; case CLIENT_STATE_CONNECTING: state = state_connecting; break; case CLIENT_STATE_CONNECTED: state = state_connected; break; case CLIENT_STATE_DISCONNECTING: state = state_disconnecting; break; } switch( stats.natt ) { case IPSEC_NATT_NONE: xport = xport_ike_esp; break; case IPSEC_NATT_CISCO: xport = xport_ike_natt_cisco; break; case IPSEC_NATT_V00: xport = xport_ike_natt_v00; break; case IPSEC_NATT_V01: xport = xport_ike_natt_v01; break; case IPSEC_NATT_V02: xport = xport_ike_natt_v02; break; case IPSEC_NATT_V03: xport = xport_ike_natt_v03; break; case IPSEC_NATT_RFC: xport = xport_ike_natt_rfc; break; } if( !stats.frag ) frag = disabled; else frag = enabled; if( !stats.dpd ) dpd = disabled; else dpd = enabled; log( 0, "current connection satus\n" " - : tunnel state = %s\n" " - : IPsec SAs in use = %i\n" " - : IPsec SAs dead = %i\n" " - : IPsec SAs failed = %i\n" " - : transport used = %s\n" " - : ike fragmenataion = %s\n" " - : dead peer detect = %s\n", state, stats.sa_good, stats.sa_dead, stats.sa_fail, xport, frag, dpd ); } ike-2.2.1+dfsg/source/ikec/ikec.h000066400000000000000000000052271223036517100165100ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #ifndef _IKEC_CLI_H_ #define _IKEC_CLI_H_ #include #include "client.h" typedef class _IKEC : public _CLIENT { protected: // initialize line editor EditLine * el; bool get_username(); bool get_password(); bool get_filepass( BDATA & path ); bool set_stats(); bool set_status( long status, BDATA * text ); public: _IKEC(); ~_IKEC(); const char * app_name(); bool log( long code, const char * format, ... ); bool read_key( char & value ); bool read_str( BDATA & value ); bool read_pwd( BDATA & value, const char * prompt ); void show_stats(); }IKEC; #endif ike-2.2.1+dfsg/source/ikec/main.cpp000066400000000000000000000065031223036517100170520ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "ikec.h" int main( int argc, char ** argv ) { IKEC ikec; signal( SIGPIPE, SIG_IGN ); ikec.log( 0, "## : VPN Connect, ver %d.%d.%d\n" "## : Copyright %i Shrew Soft Inc.\n" "## : press the key for help\n", CLIENT_VER_MAJ, CLIENT_VER_MIN, CLIENT_VER_BLD, CLIENT_YEAR ); // read our command line args if( ikec.read_opts( argc, argv ) != OPT_RESULT_SUCCESS ) { ikec.show_help(); return -1; } // load our site configuration if( ikec.config_load() ) { // autoconnect if requested if( ikec.auto_connect() ) ikec.vpn_connect( true ); } // process user input bool exit = false; while( !exit ) { char next; if( !ikec.read_key( next ) ) next = 'q'; switch( next ) { case 'c': // connect ikec.vpn_connect( true ); break; case 'd': // disconnect ikec.vpn_disconnect(); break; case 'h': // help case '?': // help ikec.log( 0, "%s", "Use the following keys to control client connectivity\n" " - : connect\n" " - : disconnect\n" " - : help\n" " - : status\n" " - : quit\n" ); break; case 'q': // quit exit = true; break; case 's': // status ikec.show_stats(); break; } } return 0; } ike-2.2.1+dfsg/source/iked/000077500000000000000000000000001223036517100154175ustar00rootroot00000000000000ike-2.2.1+dfsg/source/iked/CMakeLists.txt000066400000000000000000000047221223036517100201640ustar00rootroot00000000000000# # Shrew Soft VPN / IKE Daemon # Cross Platform Make File # # author : Matthew Grooms # : mgrooms@shrew.net # : Copyright 2007, Shrew Soft Inc # add_definitions( -D PATH_CONF=\\"${PATH_ETC}\\" ) include_directories( ${IKE_SOURCE_DIR}/source ${IKE_SOURCE_DIR}/source/iked ${IKE_SOURCE_DIR}/source/libike ${IKE_SOURCE_DIR}/source/libidb ${IKE_SOURCE_DIR}/source/libith ${IKE_SOURCE_DIR}/source/libip ${IKE_SOURCE_DIR}/source/liblog ${IKE_SOURCE_DIR}/source/libpfk ${INC_KERNEL_DIR} ) link_directories( ${IKE_SOURCE_DIR}/source/libike ${IKE_SOURCE_DIR}/source/libidb ${IKE_SOURCE_DIR}/source/libith ${IKE_SOURCE_DIR}/source/libip ${IKE_SOURCE_DIR}/source/liblog ${IKE_SOURCE_DIR}/source/libpfk ) add_executable( iked crypto.cpp conf.parse.cpp conf.token.cpp dhcp.cpp ike.cpp ike.exch.config.cpp ike.exch.inform.cpp ike.exch.phase1.cpp ike.exch.phase2.cpp ike.idb.config.cpp ike.idb.inform.cpp ike.idb.lists.cpp ike.idb.phase1.cpp ike.idb.phase2.cpp ike.idb.peer.cpp ike.idb.policy.cpp ike.idb.tunnel.cpp ike.idb.exch.cpp ike.io.admin.cpp ike.io.network.cpp ike.io.pfkey.cpp ike.keyfile.cpp ike.names.cpp ike.nethlp.cpp ike.packet.cpp ike.payload.cpp ike.peerid.cpp ike.policy.cpp ike.proposal.cpp ike.socket.cpp ike.xauth.cpp ike.xconf.cpp iked.cpp main.cpp ) target_link_libraries( iked ss_ike ss_idb ss_ith ss_ip ss_log ss_pfk crypto pthread ) if( FUNC_LIB_CRYPT ) target_link_libraries( iked crypt ) endif( FUNC_LIB_CRYPT ) # LDAP support option if( LDAP ) include_directories( ${PATH_INC_LDAP} ) target_link_libraries( iked ${PATH_LIB_LDAP} ${PATH_LIB_LBER} ) endif( LDAP ) set_source_files_properties( conf.parse.cpp GENERATED, conf.token.cpp GENERATED ) # Custom target for parser add_custom_target( ConfParser echo "Creating Conf Parser" ) # Custom command for flex add_custom_command( SOURCE conf.token.ll COMMAND ${PATH_BIN_FLEX} ARGS -d -oconf.token.cpp conf.token.ll TARGET ConfParser OUTPUTS conf.token.cpp ) # Custom command for bison add_custom_command( SOURCE conf.parse.yy COMMAND ${PATH_BIN_BISON} ARGS -oconf.parse.cpp conf.parse.yy TARGET ConfParser OUTPUTS conf.parse.cpp conf.parse.hpp location.hh position.hh stack.hh ) # install support install( TARGETS iked RUNTIME DESTINATION ${PATH_SBIN} ) install( FILES iked.8 DESTINATION ${PATH_MAN}/man8 ) install( FILES iked.conf.5 DESTINATION ${PATH_MAN}/man5 ) install( FILES iked.conf.sample DESTINATION ${PATH_ETC} ) ike-2.2.1+dfsg/source/iked/conf.parse.yy000066400000000000000000000770661223036517100200600ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ %skeleton "lalr1.cc" %defines %define "parser_class_name" "conf_parser" %{ #include #include "iked.h" #include "conf.parse.hpp" %} // The parsing context. %parse-param { IKED & iked } %lex-param { IKED & iked } %locations %debug %error-verbose // Symbols. %union { int ival; BDATA * bval; }; %{ #define YY_DECL \ yy::conf_parser::token_type \ yylex( yy::conf_parser::semantic_type * yylval, \ yy::conf_parser::location_type * yylloc, \ IKED & iked ) YY_DECL; IDB_PEER * peer; IKE_PROPOSAL proposal; IDB_LIST_PH2ID * idlist; BDATA fpass; %} %token BCB "begin section" %token ECB "end section" %token BSB "begin grouping" %token ESB "end grouping" %token EOS "end of statement" %token SEQ "sequence" %token END 0 "end of file" %token ENABLE "enable" %token DISABLE "disable" %token FORCE "force" %token DRAFT "draft" %token RFC "rfc" %token DAEMON "deamon section" %token SOCK "socket" %token IKE "ike" %token NATT "natt" %token SYSLOG "syslog" %token LL_NONE "none" %token LL_ERROR "error" %token LL_INFO "info" %token LL_DEBUG "debug" %token LL_LOUD "loud" %token LL_DECODE "decode" %token LOG_LEVEL "log level" %token LOG_FILE "log file" %token DHCP_FILE "dhcp file" %token PCAP_DECRYPT "decrypted ike pcap dump file" %token PCAP_ENCRYPT "encrypted ike pcap dump file" %token RETRY_COUNT "retry count" %token RETRY_DELAY "retry delay" %token NETGROUP "netgroup section" %token XAUTH_LDAP "xauth ldap section" %token LD_VERSION "version" %token LD_URL "url" %token LD_BASE "base" %token LD_SUBTREE "subtree" %token LD_BIND_DN "bind dn" %token LD_BIND_PW "bind pw" %token LD_ATTR_USER "user attribute" %token LD_ATTR_GROUP "group attribute" %token LD_ATTR_MEMBER "member attribute" %token XCONF_LOCAL "xconfig local section" %token NETWORK4 "network4" %token DNSS4 "domain name server" %token NBNS4 "nerbios name server" %token DNS_SUFFIX "dns suffix" %token DNS_LIST "dns list" %token BANNER "banner" %token PFS_GROUP "pfs group" %token PEER "peer section" %token CONTACT "contact type" %token INITIATOR "initiator" %token RESPONDER "responder" %token EXCHANGE "exchange type" %token MAIN "main" %token AGGRESSIVE "aggressive" %token NATT_MODE "natt mode" %token NATT_RATE "natt keepalive rate" %token DPD_MODE "dpd mode" %token DPD_DELAY "dpd notifiy delay" %token DPD_RETRY "dpd notifiy retries" %token FRAG_IKE_MODE "frag ike mode" %token FRAG_IKE_SIZE "frag ike size" %token FRAG_ESP_MODE "frag esp mode" %token FRAG_ESP_SIZE "frag esp size" %token PEERID "peer id" %token LOCAL "local" %token REMOTE "remote" %token ADDR "address" %token FQDN "fqdn" %token UFQDN "ufqdn" %token ASN1DN "asn1dn" %token KEYID "keyid" %token AUTHDATA "authdata" %token PSK "psk" %token CA "ca" %token CERT "cert" %token PKEY "pkey" %token LIFE_CHECK "lifetime check" %token OBEY "obey" %token CLAIM "claim" %token STRICT "strict" %token EXACT "exact" %token XAUTH_SOURCE "xauth source" %token XCONF_SOURCE "xconf source" %token PULL "pull" %token PUSH "push" %token LDAP "ldap" %token PLCY_MODE "policy mode" %token CONFIG "config" %token COMPAT "compat" %token PLCY_LIST "policy list section" %token INCLUDE "include" %token EXCLUDE "exclude" %token PROPOSAL "proposal section" %token ISAKMP "isakmp" %token AH "ah" %token ESP "esp" %token IPCOMP "ipcomp" %token AUTH "auth" %token HYB_XA_RSA "hybrid xauth rsa" %token MUT_XA_RSA "mutual xauth rsa" %token MUT_XA_PSK "mutual xauth psk" %token MUT_RSA "mutual rsa" %token MUT_PSK "mutual psk" %token CIPH "cipher" %token KLEN "klen" %token HASH "hash" %token MSGA "hmac" %token COMP "compress" %token DHGR "dh group" %token ALG_AES "aes" %token ALG_BLOWFISH "blowfish" %token ALG_3DES "3des" %token ALG_CAST "cast" %token ALG_DES "des" %token ALG_MD5 "md5" %token ALG_SHA1 "sha1" %token ALG_SHA2_256 "sha2-256" %token ALG_SHA2_384 "sha2-384" %token ALG_SHA2_512 "sha2-512" %token ALG_DHGR "dhgr" %token ALG_DEFLATE "deflate" %token ALG_LZS "lzs" %token LIFE_SEC "life sec" %token LIFE_KBS "life kbs" %token NUMBER "number value" %token QUOTED "quoted value" %token LABEL "label value" %token ADDRESS "address value" %token NETWORK "network value" %type NUMBER "number" %type QUOTED "quoted" %type LABEL "label" %type ADDRESS "address" %type NETWORK "network" %destructor { delete $$; } QUOTED %destructor { delete $$; } LABEL %destructor { delete $$; } ADDRESS %destructor { delete $$; } NETWORK %% /* * ROOT SECTION * */ sections : /* nothing */ | sections section ; section : daemon_section | netgroup_section | xauth_ldap_section | xconf_local_section | peer_section ; /* * DAEMON SECTION * */ daemon_section : DAEMON BCB daemon_lines ECB ; daemon_lines : /* nothing */ | daemon_lines daemon_line ; daemon_line : SOCK IKE NUMBER { IKE_SADDR saddr; memset( &saddr, 0, sizeof( saddr ) ); saddr.saddr4.sin_family = AF_INET; SET_SALEN( &saddr.saddr4, sizeof( sockaddr_in ) ); saddr.saddr4.sin_port = htons( $3 ); if( iked.socket_create( saddr, false ) != LIBIKE_OK ) error( @$, std::string( "daemon network configuration failed\n" ) ); } EOS | SOCK IKE ADDRESS NUMBER { IKE_SADDR saddr; memset( &saddr, 0, sizeof( saddr ) ); SET_SALEN( &saddr.saddr4, sizeof( sockaddr_in ) ); saddr.saddr4.sin_family = AF_INET; saddr.saddr4.sin_addr.s_addr = inet_addr( $3->text() ); saddr.saddr4.sin_port = htons( $4 ); if( iked.socket_create( saddr, false ) != LIBIKE_OK ) error( @$, std::string( "daemon network configuration failed" ) ); delete $3; } EOS | SOCK NATT NUMBER { #ifdef OPT_NATT IKE_SADDR saddr; memset( &saddr, 0, sizeof( saddr ) ); SET_SALEN( &saddr.saddr4, sizeof( sockaddr_in ) ); saddr.saddr4.sin_family = AF_INET; saddr.saddr4.sin_port = htons( $3 ); if( iked.socket_create( saddr, true ) != LIBIKE_OK ) error( @$, std::string( "daemon network configuration failed" ) ); #else error( @$, std::string( "iked was compiled without NATT support" ) ); #endif } EOS | SOCK NATT ADDRESS NUMBER { #ifdef OPT_NATT IKE_SADDR saddr; memset( &saddr, 0, sizeof( saddr ) ); SET_SALEN( &saddr.saddr4, sizeof( sockaddr_in ) ); saddr.saddr4.sin_family = AF_INET; saddr.saddr4.sin_addr.s_addr = inet_addr( $3->text() ); saddr.saddr4.sin_port = htons( $4 ); if( iked.socket_create( saddr, true ) != LIBIKE_OK ) error( @$, std::string( "daemon network configuration failed" ) ); delete $3; #else error( @$, std::string( "iked was compiled without NATT support" ) ); #endif } EOS | LOG_FILE SYSLOG { if( iked.path_log[ 0 ] == 0 ) { snprintf( iked.path_log, MAX_PATH, "iked" ); iked.logflags |= LOGFLAG_SYSTEM; } } EOS | LOG_FILE QUOTED { if( iked.path_log[ 0 ] == 0 ) snprintf( iked.path_log, MAX_PATH, "%s", $2->text() ); delete $2; } EOS | DHCP_FILE QUOTED { snprintf( iked.path_dhcp, MAX_PATH, "%s", $2->text() ); delete $2; } EOS | LOG_LEVEL LL_NONE { iked.level = LLOG_NONE; } EOS | LOG_LEVEL LL_ERROR { iked.level = LLOG_ERROR; } EOS | LOG_LEVEL LL_INFO { iked.level = LLOG_INFO; } EOS | LOG_LEVEL LL_DEBUG { iked.level = LLOG_DEBUG; } EOS | LOG_LEVEL LL_LOUD { iked.level = LLOG_LOUD; } EOS | LOG_LEVEL LL_DECODE { iked.level = LLOG_DECODE; } EOS | PCAP_ENCRYPT QUOTED { snprintf( iked.path_decrypt, MAX_PATH, "%s", $2->text() ); iked.dump_decrypt = true; delete $2; } EOS | PCAP_DECRYPT QUOTED { snprintf( iked.path_encrypt, MAX_PATH, "%s", $2->text() ); iked.dump_encrypt = true; delete $2; } EOS | RETRY_DELAY NUMBER { iked.retry_delay = $2; } EOS | RETRY_COUNT NUMBER { iked.retry_count = $2; } EOS ; /* * NETGROUP SECTION * */ netgroup_section : NETGROUP LABEL { idlist = new IDB_LIST_PH2ID; if( idlist == NULL ) error( @$, std::string( "unable to allocate idlist for netgroup" ) + $2->text() ); idlist->name.set( *$2 ); iked.idb_list_netgrp.add_entry( idlist ); delete $2; } BCB netgroup_lines ECB ; netgroup_lines : /* nothing */ | netgroup_lines netgroup_line ; netgroup_line : NETWORK { char * pos = strchr( $1->text(), '/' ); *pos = '\0'; IKE_PH2ID ph2id; memset( &ph2id, 0, sizeof( ph2id ) ); ph2id.type = ISAKMP_ID_IPV4_ADDR_SUBNET; ph2id.addr1.s_addr = inet_addr( $1->text() ); ph2id.addr2.s_addr = 0; long bits = strtol( pos + 1, NULL, 10 ); for( long i = 0; i < bits; i++ ) { ph2id.addr2.s_addr >>= 1; ph2id.addr2.s_addr |= 0x80000000; } ph2id.addr2.s_addr = htonl( ph2id.addr2.s_addr ); idlist->add( ph2id ); delete $1; } EOS ; /* * LDAP SECTION * */ xauth_ldap_section : XAUTH_LDAP { #ifndef OPT_LDAP error( @$, std::string( "iked was compiled without ldap support" ) ); #endif } BCB xauth_ldap_lines ECB ; xauth_ldap_lines : /* nothing */ | xauth_ldap_lines xauth_ldap_line ; xauth_ldap_line : LD_VERSION NUMBER { #ifdef OPT_LDAP if( ( $2 < 2 ) && ( $2 > 3 ) ) error( @$, std::string( "ldap version must be 2 or 3" ) ); iked.xauth_ldap.version = $2; #endif } EOS | LD_URL QUOTED { #ifdef OPT_LDAP iked.xauth_ldap.url.set( *$2 ); delete $2; #endif } EOS | LD_BASE QUOTED { #ifdef OPT_LDAP iked.xauth_ldap.base.set( *$2 ); delete $2; #endif } EOS | LD_SUBTREE ENABLE { #ifdef OPT_LDAP iked.xauth_ldap.subtree = true; #endif } EOS | LD_SUBTREE DISABLE { #ifdef OPT_LDAP iked.xauth_ldap.subtree = false; #endif } EOS | LD_BIND_DN QUOTED { #ifdef OPT_LDAP iked.xauth_ldap.bind_dn.set( *$2 ); delete $2; #endif } EOS | LD_BIND_PW QUOTED { #ifdef OPT_LDAP iked.xauth_ldap.bind_pw.set( *$2 ); delete $2; #endif } EOS | LD_ATTR_USER QUOTED { #ifdef OPT_LDAP iked.xauth_ldap.attr_user.set( *$2 ); delete $2; #endif } EOS | LD_ATTR_GROUP QUOTED { #ifdef OPT_LDAP iked.xauth_ldap.attr_group.set( *$2 ); delete $2; #endif } EOS | LD_ATTR_MEMBER QUOTED { #ifdef OPT_LDAP iked.xauth_ldap.attr_member.set( *$2 ); delete $2; #endif } EOS ; /* * XCONF LOCAL SECTION * */ xconf_local_section : XCONF_LOCAL BCB xconf_local_lines ECB ; xconf_local_lines : /* nothing */ | xconf_local_lines xconf_local_line ; xconf_local_line : NETWORK4 NETWORK { iked.xconf_local.config.opts |= ( IPSEC_OPTS_ADDR | IPSEC_OPTS_MASK ); char * pos = strchr( $2->text(), '/' ); *pos = '\0'; in_addr base; base.s_addr = inet_addr( $2->text() ); long bits = strtol( pos + 1, NULL, 10 ); iked.xconf_local.pool4_set( base, bits, 0 ); delete $2; } EOS | NETWORK4 NETWORK NUMBER { iked.xconf_local.config.opts |= ( IPSEC_OPTS_ADDR | IPSEC_OPTS_MASK ); char * pos = strchr( $2->text(), '/' ); *pos = '\0'; in_addr base; base.s_addr = inet_addr( $2->text() ); long bits = strtol( pos + 1, NULL, 10 ); iked.xconf_local.pool4_set( base, bits, $3 ); delete $2; } EOS | DNSS4 xconf_local_dns_servers { iked.xconf_local.config.opts |= IPSEC_OPTS_DNSS; } EOS | NBNS4 xconf_local_nbn_servers { iked.xconf_local.config.opts |= IPSEC_OPTS_NBNS; } EOS | DNS_SUFFIX QUOTED { iked.xconf_local.config.opts |= IPSEC_OPTS_DOMAIN; long len = $2->size(); if( len >= CONF_STRLEN ) len = CONF_STRLEN - 1; memcpy( iked.xconf_local.config.nscfg.dnss_suffix, $2->text(), len ); iked.xconf_local.config.nscfg.dnss_suffix[ len ] = 0; delete $2; } EOS | DNS_LIST xconf_local_dns_names { iked.xconf_local.config.opts |= IPSEC_OPTS_SPLITDNS; } EOS | BANNER QUOTED { iked.xconf_local.config.opts |= IPSEC_OPTS_BANNER; FILE * fp = fopen( $2->text(), "r" ); if( fp == NULL ) error( @$, std::string( "unable to load file " ) + $2->text() ); long size; char buff[ CONF_STRLEN ]; while( ( size = fread( buff, 1, CONF_STRLEN, fp ) ) > 0 ) iked.xconf_local.banner.add( buff, size ); delete $2; } EOS | PFS_GROUP NUMBER { iked.xconf_local.config.opts |= IPSEC_OPTS_PFS; iked.xconf_local.config.dhgr = $2; } EOS ; xconf_local_dns_servers : /* nothing */ | xconf_local_dns_servers xconf_local_dns_server ; xconf_local_dns_server : ADDRESS { int count = iked.xconf_local.config.nscfg.dnss_count; if( count <= IPSEC_DNSS_MAX ) { iked.xconf_local.config.nscfg.dnss_list[ count ].s_addr = inet_addr( $1->text() ); iked.xconf_local.config.nscfg.dnss_count++; } delete $1; } ; xconf_local_nbn_servers : /* nothing */ | xconf_local_nbn_servers xconf_local_nbn_server ; xconf_local_nbn_server : ADDRESS { int count = iked.xconf_local.config.nscfg.nbns_count; if( count <= IPSEC_NBNS_MAX ) { iked.xconf_local.config.nscfg.nbns_list[ count ].s_addr = inet_addr( $1->text() ); iked.xconf_local.config.nscfg.nbns_count++; } delete $1; } ; xconf_local_dns_names : /* nothing */ | xconf_local_dns_names xconf_local_dns_name ; xconf_local_dns_name : QUOTED { iked.xconf_local.domains.add( *$1 ); delete $1; } ; /* * PEER SECTION * */ peer_section : PEER ADDRESS { // // new peer object // peer = new IDB_PEER( NULL ); // // set peer default values // peer->contact = IPSEC_CONTACT_BOTH; peer->natt_rate = 30; peer->dpd_delay = 15; peer->dpd_retry = 5; peer->frag_ike_size = 520; peer->frag_esp_size = 520; peer->life_check = LTIME_CLAIM; SET_SALEN( &peer->saddr.saddr4, sizeof( sockaddr_in ) ); peer->saddr.saddr4.sin_family = AF_INET; peer->saddr.saddr4.sin_port = htons( LIBIKE_IKE_PORT ); peer->saddr.saddr4.sin_addr.s_addr = inet_addr( $2->text() ); peer->xauth_source = &iked.xauth_local; peer->xconf_source = &iked.xconf_local; peer->xconf_mode = CONFIG_MODE_PULL; delete $2; } BCB peer_lines ECB { peer->add( true ); peer->dec( true ); } | PEER ADDRESS NUMBER { // // new peer object // peer = new IDB_PEER( NULL ); // // set peer default values // peer->contact = IPSEC_CONTACT_BOTH; peer->natt_rate = 30; peer->dpd_delay = 15; peer->dpd_retry = 5; peer->frag_ike_size = 520; peer->frag_esp_size = 520; peer->life_check = LTIME_CLAIM; SET_SALEN( &peer->saddr.saddr4, sizeof( sockaddr_in ) ); peer->saddr.saddr4.sin_family = AF_INET; peer->saddr.saddr4.sin_port = htons( $3 ); peer->saddr.saddr4.sin_addr.s_addr = inet_addr( $2->text() ); peer->xauth_source = &iked.xauth_local; peer->xconf_source = &iked.xconf_local; peer->xconf_mode = CONFIG_MODE_PULL; delete $2; } BCB peer_lines ECB { peer->add( true ); peer->dec( true ); } ; peer_lines : /* nothing */ | peer_lines peer_line ; peer_line : CONTACT INITIATOR { peer->contact = IPSEC_CONTACT_INIT; } EOS | CONTACT RESPONDER { peer->contact = IPSEC_CONTACT_RESP; } EOS | EXCHANGE MAIN { peer->exchange = ISAKMP_EXCH_IDENT_PROTECT; } EOS | EXCHANGE AGGRESSIVE { peer->exchange = ISAKMP_EXCH_AGGRESSIVE; } EOS | NATT_MODE ENABLE { #ifdef OPT_NATT peer->natt_mode = IPSEC_NATT_ENABLE; #else error( @$, std::string( "iked was compiled without NATT support" ) ); #endif } EOS | NATT_MODE DISABLE { #ifdef OPT_NATT peer->natt_mode = IPSEC_NATT_DISABLE; #else error( @$, std::string( "iked was compiled without NATT support" ) ); #endif } EOS | NATT_MODE FORCE { #ifdef OPT_NATT peer->natt_mode = IPSEC_NATT_FORCE_RFC; #else error( @$, std::string( "iked was compiled without NATT support" ) ); #endif } EOS | NATT_MODE FORCE DRAFT { #if defined( OPT_NATT ) && !defined( __APPLE ) peer->natt_mode = IPSEC_NATT_FORCE_DRAFT; #else # ifndef __APPLE__ error( @$, std::string( "iked was compiled without NATT support" ) ); # else error( @$, std::string( "your platform does not support NAT v00/01" ) ); # endif #endif } EOS | NATT_MODE FORCE RFC { #ifdef OPT_NATT peer->natt_mode = IPSEC_NATT_FORCE_RFC; #else error( @$, std::string( "iked was compiled without NATT support" ) ); #endif } EOS | NATT_RATE NUMBER { #ifdef OPT_NATT peer->natt_rate = $2; #else error( @$, std::string( "iked was compiled without NATT support" ) ); #endif } EOS | DPD_MODE ENABLE { peer->dpd_mode = IPSEC_DPD_ENABLE; } EOS | DPD_MODE DISABLE { peer->dpd_mode = IPSEC_DPD_DISABLE; } EOS | DPD_MODE FORCE { peer->dpd_mode = IPSEC_DPD_FORCE; } EOS | DPD_DELAY NUMBER { peer->dpd_delay = $2; } EOS | DPD_RETRY NUMBER { peer->dpd_retry = $2; } EOS | FRAG_IKE_MODE ENABLE { peer->frag_ike_mode = IPSEC_FRAG_ENABLE; } EOS | FRAG_IKE_MODE DISABLE { peer->frag_ike_mode = IPSEC_FRAG_DISABLE; } EOS | FRAG_IKE_MODE FORCE { peer->frag_ike_mode = IPSEC_FRAG_FORCE; } EOS | FRAG_IKE_SIZE NUMBER { peer->frag_ike_size = $2; } EOS | FRAG_ESP_MODE ENABLE { peer->frag_esp_mode = IPSEC_FRAG_ENABLE; } EOS | FRAG_ESP_MODE DISABLE { peer->frag_esp_mode = IPSEC_FRAG_DISABLE; } EOS | FRAG_ESP_SIZE NUMBER { peer->frag_esp_size = $2; } EOS | PEERID LOCAL ADDR { peer->idtype_l = ISAKMP_ID_IPV4_ADDR; } EOS | PEERID LOCAL ADDR ADDRESS { peer->idtype_l = ISAKMP_ID_IPV4_ADDR; peer->iddata_l.set( *$4 ); delete $4; } EOS | PEERID LOCAL FQDN QUOTED { peer->idtype_l = ISAKMP_ID_FQDN; peer->iddata_l.set( $4->buff(), $4->size() - 1 ); delete $4; } EOS | PEERID LOCAL UFQDN QUOTED { peer->idtype_l = ISAKMP_ID_USER_FQDN; peer->iddata_l.set( $4->buff(), $4->size() - 1 ); delete $4; } EOS | PEERID LOCAL KEYID QUOTED { peer->idtype_l = ISAKMP_ID_KEY_ID; peer->iddata_l.set( $4->buff(), $4->size() - 1 ); delete $4; } EOS | PEERID LOCAL ASN1DN { peer->idtype_l = ISAKMP_ID_ASN1_DN; } EOS | PEERID LOCAL ASN1DN QUOTED { peer->idtype_l = ISAKMP_ID_ASN1_DN; peer->iddata_l.set( *$4 ); delete $4; } EOS | PEERID REMOTE ADDR { peer->idtype_r = ISAKMP_ID_IPV4_ADDR; } EOS | PEERID REMOTE ADDR ADDRESS { peer->idtype_r = ISAKMP_ID_IPV4_ADDR; peer->iddata_r.set( *$4 ); delete $4; } EOS | PEERID REMOTE FQDN QUOTED { peer->idtype_r = ISAKMP_ID_FQDN; peer->iddata_r.set( $4->buff(), $4->size() - 1 ); delete $4; } EOS | PEERID REMOTE UFQDN QUOTED { peer->idtype_r = ISAKMP_ID_USER_FQDN; peer->iddata_r.set( $4->buff(), $4->size() - 1 ); delete $4; } EOS | PEERID REMOTE KEYID QUOTED { peer->idtype_r = ISAKMP_ID_KEY_ID; peer->iddata_r.set( $4->buff(), $4->size() - 1 ); delete $4; } EOS | PEERID REMOTE ASN1DN { peer->idtype_r = ISAKMP_ID_ASN1_DN; } EOS | PEERID REMOTE ASN1DN QUOTED { peer->idtype_r = ISAKMP_ID_ASN1_DN; peer->iddata_r.set( *$4 ); delete $4; } EOS | AUTHDATA PSK QUOTED { peer->psk.set( *$3 ); delete $3; } EOS | AUTHDATA CA QUOTED { fpass.del(); if( iked.cert_load( peer->cert_r, $3->text(), true, fpass ) != FILE_OK ) error( @$, std::string( "unable to load file " ) + $3->text() ); delete $3; } EOS | AUTHDATA CA QUOTED QUOTED { fpass = *$4; if( iked.cert_load( peer->cert_r, $3->text(), true, fpass ) != FILE_OK ) error( @$, std::string( "unable to load file " ) + $3->text() ); delete $3; delete $4; } EOS | AUTHDATA CERT QUOTED { fpass.del(); if( iked.cert_load( peer->cert_l, $3->text(), false, fpass ) != FILE_OK ) error( @$, std::string( "unable to load file " ) + $3->text() ); delete $3; } EOS | AUTHDATA CERT QUOTED QUOTED { fpass = *$4; if( iked.cert_load( peer->cert_l, $3->text(), false, fpass ) != FILE_OK ) error( @$, std::string( "unable to load file " ) + $3->text() ); delete $3; delete $4; } EOS | AUTHDATA PKEY QUOTED { fpass.del(); if( iked.prvkey_rsa_load( peer->cert_k, $3->text(), fpass ) != FILE_OK ) error( @$, std::string( "unable to load file " ) + $3->text() ); delete $3; } EOS | AUTHDATA PKEY QUOTED QUOTED { fpass = *$4; if( iked.prvkey_rsa_load( peer->cert_k, $3->text(), fpass ) != FILE_OK ) error( @$, std::string( "unable to load file " ) + $3->text() ); delete $3; delete $4; } EOS | LIFE_CHECK OBEY { peer->life_check = LTIME_OBEY; } EOS | LIFE_CHECK CLAIM { peer->life_check = LTIME_CLAIM; } EOS | LIFE_CHECK STRICT { peer->life_check = LTIME_STRICT; } EOS | LIFE_CHECK EXACT { peer->life_check = LTIME_EXACT; } EOS | XAUTH_SOURCE LOCAL { peer->xauth_source = &iked.xauth_local; } EOS | XAUTH_SOURCE LOCAL QUOTED { peer->xauth_source = &iked.xauth_local; peer->xauth_group.set( *$3 ); delete $3; } EOS | XAUTH_SOURCE LDAP { #ifdef OPT_LDAP if( !iked.xauth_ldap.url.size() ) error( @$, std::string( "conf source is ldap but no url is defined" ) ); peer->xauth_source = &iked.xauth_ldap; #else error( @$, std::string( "iked was compiled without ldap support" ) ); #endif } EOS | XAUTH_SOURCE LDAP QUOTED { #ifdef OPT_LDAP if( !iked.xauth_ldap.url.size() ) error( @$, std::string( "conf source is ldap but no url is defined" ) ); peer->xauth_source = &iked.xauth_ldap; peer->xauth_group.set( *$3 ); delete $3; #else error( @$, std::string( "iked was compiled without ldap support" ) ); #endif } EOS | XCONF_SOURCE LOCAL { peer->xconf_source = &iked.xconf_local; peer->xconf_mode = CONFIG_MODE_PULL; } EOS | XCONF_SOURCE LOCAL PULL { peer->xconf_source = &iked.xconf_local; peer->xconf_mode = CONFIG_MODE_PULL; } EOS | XCONF_SOURCE LOCAL PUSH { peer->xconf_source = &iked.xconf_local; peer->xconf_mode = CONFIG_MODE_PUSH; } EOS | PLCY_MODE DISABLE { peer->plcy_mode = POLICY_MODE_DISABLE; } EOS | PLCY_MODE COMPAT { peer->plcy_mode = POLICY_MODE_COMPAT; } EOS | PLCY_MODE CONFIG { peer->plcy_mode = POLICY_MODE_CONFIG; } EOS | PLCY_LIST BCB plcy_list_lines ECB | PROPOSAL ISAKMP { memset( &proposal, 0, sizeof( proposal ) ); proposal.proto = ISAKMP_PROTO_ISAKMP; proposal.xform = ISAKMP_KEY_IKE; proposal.dhgr_id = IKE_GRP_GROUP2; } BCB proposal_lines_isakmp ECB { peer->proposals.add( &proposal, true ); } | PROPOSAL AH { memset( &proposal, 0, sizeof( proposal ) ); proposal.proto = ISAKMP_PROTO_IPSEC_AH; } BCB proposal_lines_ah ECB { peer->proposals.add( &proposal, true ); } | PROPOSAL ESP { memset( &proposal, 0, sizeof( proposal ) ); proposal.proto = ISAKMP_PROTO_IPSEC_ESP; } BCB proposal_lines_esp ECB { peer->proposals.add( &proposal, true ); } | PROPOSAL IPCOMP { memset( &proposal, 0, sizeof( proposal ) ); proposal.proto = ISAKMP_PROTO_IPCOMP; } BCB proposal_lines_ipcomp ECB { peer->proposals.add( &proposal, true ); } ; plcy_list_lines : /* nothing */ | plcy_list_lines plcy_list_line ; plcy_list_line : INCLUDE LABEL { long index = 0; while( true ) { idlist = static_cast( iked.idb_list_netgrp.get_entry( index++ ) ); if( idlist == NULL ) break; if( !strcmp( $2->text(), idlist->name.text() ) ) break; } if( idlist == NULL ) error( @$, std::string( "unknown netgroup " ) + $2->text() ); peer->netmaps.add( idlist, UNITY_SPLIT_INCLUDE, NULL ); delete $2; } EOS | INCLUDE LABEL QUOTED { long index = 0; while( true ) { idlist = static_cast( iked.idb_list_netgrp.get_entry( index++ ) ); if( idlist == NULL ) break; if( !strcmp( $2->text(), idlist->name.text() ) ) break; } if( idlist == NULL ) error( @$, std::string( "unknown netgroup " ) + $2->text() ); peer->netmaps.add( idlist, UNITY_SPLIT_INCLUDE, $3 ); delete $2; delete $3; } EOS | EXCLUDE LABEL { long index = 0; while( true ) { idlist = static_cast( iked.idb_list_netgrp.get_entry( index++ ) ); if( idlist == NULL ) break; if( !strcmp( $2->text(), idlist->name.text() ) ) break; } if( idlist == NULL ) error( @$, std::string( "unknown netgroup " ) + $2->text() ); peer->netmaps.add( idlist, UNITY_SPLIT_EXCLUDE, NULL ); delete $2; } EOS | EXCLUDE LABEL QUOTED { long index = 0; while( true ) { idlist = static_cast( iked.idb_list_netgrp.get_entry( index++ ) ); if( idlist == NULL ) break; if( !strcmp( $2->text(), idlist->name.text() ) ) break; } if( idlist == NULL ) error( @$, std::string( "unknown netgroup " ) + $2->text() ); peer->netmaps.add( idlist, UNITY_SPLIT_EXCLUDE, $3 ); delete $2; delete $3; } EOS ; proposal_lines_isakmp : /* nothing */ | proposal_lines_isakmp proposal_line_isakmp ; proposal_line_isakmp : AUTH HYB_XA_RSA { proposal.auth_id = HYBRID_AUTH_INIT_RSA; } EOS | AUTH MUT_XA_RSA { proposal.auth_id = XAUTH_AUTH_INIT_RSA; } EOS | AUTH MUT_XA_PSK { proposal.auth_id = XAUTH_AUTH_INIT_PSK; } EOS | AUTH MUT_RSA { proposal.auth_id = IKE_AUTH_SIG_RSA; } EOS | AUTH MUT_PSK { proposal.auth_id = IKE_AUTH_PRESHARED_KEY; } EOS | CIPH ALG_AES { proposal.ciph_id = IKE_CIPHER_AES; } EOS | CIPH ALG_BLOWFISH { proposal.ciph_id = IKE_CIPHER_BLOWFISH; } EOS | CIPH ALG_3DES { proposal.ciph_id = IKE_CIPHER_3DES; } EOS | CIPH ALG_CAST { proposal.ciph_id = IKE_CIPHER_CAST; } EOS | CIPH ALG_DES { proposal.ciph_id = IKE_CIPHER_DES; } EOS | KLEN NUMBER { proposal.ciph_kl = $2; } EOS | HASH ALG_MD5 { proposal.hash_id = IKE_HASH_MD5; } EOS | HASH ALG_SHA1 { proposal.hash_id = IKE_HASH_SHA1; } EOS | HASH ALG_SHA2_256 { proposal.hash_id = IKE_HASH_SHA2_256; } EOS | HASH ALG_SHA2_384 { proposal.hash_id = IKE_HASH_SHA2_384; } EOS | HASH ALG_SHA2_512 { proposal.hash_id = IKE_HASH_SHA2_512; } EOS | DHGR NUMBER { switch( $2 ) { case 1: proposal.dhgr_id = IKE_GRP_GROUP1; break; case 2: proposal.dhgr_id = IKE_GRP_GROUP2; break; case 5: proposal.dhgr_id = IKE_GRP_GROUP5; break; case 14: proposal.dhgr_id = IKE_GRP_GROUP14; break; case 15: proposal.dhgr_id = IKE_GRP_GROUP15; break; case 16: proposal.dhgr_id = IKE_GRP_GROUP16; break; case 17: proposal.dhgr_id = IKE_GRP_GROUP17; break; case 18: proposal.dhgr_id = IKE_GRP_GROUP18; break; default: error( @$, std::string( "invalid dhgrp id" ) ); break; } } EOS | LIFE_SEC NUMBER { proposal.life_sec = $2; } EOS | LIFE_KBS NUMBER { proposal.life_kbs = $2; } EOS ; proposal_lines_ah : /* nothing */ | proposal_lines_ah proposal_line_ah ; proposal_line_ah : MSGA ALG_MD5 { proposal.xform = ISAKMP_AH_MD5; proposal.hash_id = ISAKMP_AUTH_HMAC_MD5; } EOS | MSGA ALG_SHA1 { proposal.xform = ISAKMP_AH_SHA; proposal.hash_id = ISAKMP_AUTH_HMAC_SHA1; } EOS | MSGA ALG_SHA2_256 { proposal.xform = ISAKMP_AH_SHA256; proposal.hash_id = ISAKMP_AUTH_HMAC_SHA2_256; } EOS | MSGA ALG_SHA2_384 { proposal.xform = ISAKMP_AH_SHA384; proposal.hash_id = ISAKMP_AUTH_HMAC_SHA2_384; } EOS | MSGA ALG_SHA2_512 { proposal.xform = ISAKMP_AH_SHA512; proposal.hash_id = ISAKMP_AUTH_HMAC_SHA2_512; } EOS | DHGR NUMBER { switch( $2 ) { case 1: proposal.dhgr_id = IKE_GRP_GROUP1; break; case 2: proposal.dhgr_id = IKE_GRP_GROUP2; break; case 5: proposal.dhgr_id = IKE_GRP_GROUP5; break; case 14: proposal.dhgr_id = IKE_GRP_GROUP14; break; case 15: proposal.dhgr_id = IKE_GRP_GROUP15; break; case 16: proposal.dhgr_id = IKE_GRP_GROUP16; break; case 17: proposal.dhgr_id = IKE_GRP_GROUP17; break; case 18: proposal.dhgr_id = IKE_GRP_GROUP18; break; default: error( @$, std::string( "invalid dhgrp id" ) ); break; } } EOS | LIFE_SEC NUMBER { proposal.life_sec = $2; } EOS | LIFE_KBS NUMBER { proposal.life_kbs = $2; } EOS ; proposal_lines_esp : /* nothing */ | proposal_lines_esp proposal_line_esp ; proposal_line_esp : CIPH ALG_AES { proposal.xform = ISAKMP_ESP_AES; } EOS | CIPH ALG_BLOWFISH { proposal.xform = ISAKMP_ESP_BLOWFISH; } EOS | CIPH ALG_3DES { proposal.xform = ISAKMP_ESP_3DES; } EOS | CIPH ALG_CAST { proposal.xform = ISAKMP_ESP_CAST; } EOS | CIPH ALG_DES { proposal.xform = ISAKMP_ESP_DES; } EOS | KLEN NUMBER { proposal.ciph_kl = $2; } EOS | MSGA ALG_MD5 { proposal.hash_id = ISAKMP_AUTH_HMAC_MD5; } EOS | MSGA ALG_SHA1 { proposal.hash_id = ISAKMP_AUTH_HMAC_SHA1; } EOS | MSGA ALG_SHA2_256 { proposal.hash_id = ISAKMP_AUTH_HMAC_SHA2_256; } EOS | MSGA ALG_SHA2_384 { proposal.hash_id = ISAKMP_AUTH_HMAC_SHA2_384; } EOS | MSGA ALG_SHA2_512 { proposal.hash_id = ISAKMP_AUTH_HMAC_SHA2_512; } EOS | DHGR NUMBER { switch( $2 ) { case 1: proposal.dhgr_id = IKE_GRP_GROUP1; break; case 2: proposal.dhgr_id = IKE_GRP_GROUP2; break; case 5: proposal.dhgr_id = IKE_GRP_GROUP5; break; case 14: proposal.dhgr_id = IKE_GRP_GROUP14; break; case 15: proposal.dhgr_id = IKE_GRP_GROUP15; break; case 16: proposal.dhgr_id = IKE_GRP_GROUP16; break; case 17: proposal.dhgr_id = IKE_GRP_GROUP17; break; case 18: proposal.dhgr_id = IKE_GRP_GROUP18; break; default: error( @$, std::string( "invalid dhgrp id" ) ); break; } } EOS | LIFE_SEC NUMBER { proposal.life_sec = $2; } EOS | LIFE_KBS NUMBER { proposal.life_kbs = $2; } EOS ; proposal_lines_ipcomp : /* nothing */ | proposal_lines_ipcomp proposal_line_ipcomp ; proposal_line_ipcomp : COMP ALG_DEFLATE { proposal.xform = ISAKMP_IPCOMP_DEFLATE; } EOS | COMP ALG_LZS { proposal.xform = ISAKMP_IPCOMP_LZS; } EOS | LIFE_SEC NUMBER { proposal.life_sec = $2; } EOS | LIFE_KBS NUMBER { proposal.life_kbs = $2; } EOS ; %% void yy::conf_parser::error( const yy::conf_parser::location_type & l, const std::string & m ) { iked.log.txt( LLOG_ERROR, "%s ( line %i, col %i )\n", m.c_str(), l.end.line, l.end.column ); exit( -1 ); iked.conf_fail = true; } ike-2.2.1+dfsg/source/iked/conf.token.ll000066400000000000000000000266151223036517100200260ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ %{ #include #include #include #include #include "iked.h" #include "conf.parse.hpp" #define YY_DECL \ yy::conf_parser::token_type \ yylex( yy::conf_parser::semantic_type * yylval, \ yy::conf_parser::location_type * yylloc, \ IKED & iked ) YY_DECL; #define yyterminate() return token::END int yy_first_time = 1; %} %option noyywrap nounput batch debug /* * TYPES * */ nl \n ws [ \t]+ semic \; bcb \{ ecb \} quoted \"[^"]*\" number [0-9]+ label [0-9A-Za-z_\-]+ network [0-9\.]+"/"[0-9]+ address [0-9\.]+ comment \#.* /* * SECTIONS * */ %s SEC_ROOT %s SEC_DAEMON %s SEC_NETGROUP %s SEC_XA_LDAP %s SEC_XC_LOCAL %s SEC_PEER %s SEC_PLCY %s SEC_PROP %{ #define YY_USER_ACTION yylloc->columns( yyleng ); %} %% %{ yylloc->step(); %} %{ typedef yy::conf_parser::token token; if( yy_first_time ) { BEGIN SEC_ROOT; yy_first_time = 0; } %} daemon { BEGIN SEC_DAEMON; return( token::DAEMON ); } {bcb} { return( token::BCB ); } socket { return( token::SOCK ); } ike { return( token::IKE ); } natt { return( token::NATT ); } syslog { return( token::SYSLOG ); } none { return( token::LL_NONE ); } error { return( token::LL_ERROR ); } info { return( token::LL_INFO ); } debug { return( token::LL_DEBUG ); } loud { return( token::LL_LOUD ); } decode { return( token::LL_DECODE ); } log_level { return( token::LOG_LEVEL ); } log_file { return( token::LOG_FILE ); } dhcp_file { return( token::DHCP_FILE ); } pcap_decrypt { return( token::PCAP_DECRYPT ); } pcap_encrypt { return( token::PCAP_ENCRYPT ); } retry_delay { return( token::RETRY_DELAY ); } retry_count { return( token::RETRY_COUNT ); } {ecb} { BEGIN SEC_ROOT; return( token::ECB ); } netgroup { BEGIN SEC_NETGROUP; return( token::NETGROUP ); } {bcb} { return( token::BCB ); } {ecb} { BEGIN SEC_ROOT; return( token::ECB ); } xauth_ldap { BEGIN SEC_XA_LDAP; return( token::XAUTH_LDAP ); } {bcb} { return( token::BCB ); } version { return( token::LD_VERSION ); } url { return( token::LD_URL ); } base { return( token::LD_BASE ); } subtree { return( token::LD_SUBTREE ); } enable { return( token::ENABLE ); } disable { return( token::DISABLE ); } bind_dn { return( token::LD_BIND_DN ); } bind_pw { return( token::LD_BIND_PW ); } attr_user { return( token::LD_ATTR_USER ); } attr_group { return( token::LD_ATTR_GROUP ); } attr_member { return( token::LD_ATTR_MEMBER ); } {ecb} { BEGIN SEC_ROOT; return( token::ECB ); } xconf_local { BEGIN SEC_XC_LOCAL; return( token::XCONF_LOCAL ); } {bcb} { return( token::BCB ); } network4 { return( token::NETWORK4 ); } dnss4 { return( token::DNSS4 ); } nbns4 { return( token::NBNS4 ); } dns_suffix { return( token::DNS_SUFFIX ); } dns_list { return( token::DNS_LIST ); } banner { return( token::BANNER ); } pfs_group { return( token::PFS_GROUP ); } {ecb} { BEGIN SEC_ROOT; return( token::ECB ); } peer { BEGIN SEC_PEER; return( token::PEER ); } {bcb} { return( token::BCB ); } contact { return( token::CONTACT ); } initiator { return( token::INITIATOR ); } responder { return( token::RESPONDER ); } exchange { return( token::EXCHANGE ); } main { return( token::MAIN ); } aggressive { return( token::AGGRESSIVE ); } enable { return( token::ENABLE ); } disable { return( token::DISABLE ); } force { return( token::FORCE ); } draft { return( token::DRAFT ); } rfc { return( token::RFC ); } natt_mode { return( token::NATT_MODE ); } natt_rate { return( token::NATT_RATE ); } dpd_mode { return( token::DPD_MODE ); } dpd_delay { return( token::DPD_DELAY ); } dpd_retry { return( token::DPD_RETRY ); } frag_ike_mode { return( token::FRAG_IKE_MODE ); } frag_ike_size { return( token::FRAG_IKE_SIZE ); } frag_esp_mode { return( token::FRAG_ESP_MODE ); } frag_esp_size { return( token::FRAG_ESP_SIZE ); } peerid { return( token::PEERID ); } local { return( token::LOCAL ); } remote { return( token::REMOTE ); } address { return( token::ADDR ); } fqdn { return( token::FQDN ); } ufqdn { return( token::UFQDN ); } keyid { return( token::KEYID ); } asn1dn { return( token::ASN1DN ); } authdata { return( token::AUTHDATA ); } psk { return( token::PSK ); } ca { return( token::CA ); } cert { return( token::CERT ); } pkey { return( token::PKEY ); } life_check { return( token::LIFE_CHECK ); } obey { return( token::OBEY ); } claim { return( token::CLAIM ); } strict { return( token::STRICT ); } exact { return( token::EXACT ); } xauth_source { return( token::XAUTH_SOURCE ); } xconf_source { return( token::XCONF_SOURCE ); } pull { return( token::PULL ); } push { return( token::PUSH ); } system { return( token::LOCAL ); } ldap { return( token::LDAP ); } plcy_mode { return( token::PLCY_MODE ); } config { return( token::CONFIG ); } compat { return( token::COMPAT ); } plcy_list { BEGIN SEC_PLCY; return( token::PLCY_LIST ); } proposal { BEGIN SEC_PROP; return( token::PROPOSAL ); } {ecb} { BEGIN SEC_ROOT; return( token::ECB ); } {bcb} { return( token::BCB ); } include { return( token::INCLUDE ); } exclude { return( token::EXCLUDE ); } {ecb} { BEGIN SEC_PEER; return( token::ECB ); } {bcb} { return( token::BCB ); } isakmp { return( token::ISAKMP ); } ah { return( token::AH ); } esp { return( token::ESP ); } ipcomp { return( token::IPCOMP ); } auth { return( token::AUTH ); } hybrid_xauth_rsa { return( token::HYB_XA_RSA ); } mutual_xauth_rsa { return( token::MUT_XA_RSA ); } mutual_xauth_psk { return( token::MUT_XA_PSK ); } mutual_rsa { return( token::MUT_RSA ); } mutual_psk { return( token::MUT_PSK ); } ciph { return( token::CIPH ); } klen { return( token::KLEN ); } hash { return( token::HASH ); } hmac { return( token::MSGA ); } dhgr { return( token::DHGR ); } comp { return( token::COMP ); } aes { return( token::ALG_AES ); } blowfish { return( token::ALG_BLOWFISH ); } 3des { return( token::ALG_3DES ); } cast { return( token::ALG_CAST ); } des { return( token::ALG_DES ); } md5 { return( token::ALG_MD5 ); } sha1 { return( token::ALG_SHA1 ); } sha2_256 { return( token::ALG_SHA2_256 ); } sha2_384 { return( token::ALG_SHA2_384 ); } sha2_512 { return( token::ALG_SHA2_512 ); } deflate { return( token::ALG_DEFLATE ); } lzs { return( token::ALG_LZS ); } life_sec { return( token::LIFE_SEC ); } life_kbs { return( token::LIFE_KBS ); } {ecb} { BEGIN SEC_PEER; return( token::ECB ); } {ws}+ ; {comment} ; {nl}+ yylloc->lines( yyleng ); {semic} return( token::EOS ); {quoted} { int len = strlen( yytext ); if( len < 3 ) return token::SEQ; yylval->bval = new BDATA; yylval->bval->set( yytext + 1, len - 2 ); yylval->bval->add( 0, 1 ); return token::QUOTED; } {number} { yylval->ival = strtol( yytext, NULL, 10 ); return token::NUMBER; } {label} { yylval->bval = new BDATA; yylval->bval->set( yytext, strlen( yytext ) ); yylval->bval->add( 0, 1 ); return token::LABEL; } {network} { yylval->bval = new BDATA; yylval->bval->set( yytext, strlen( yytext ) ); yylval->bval->add( 0, 1 ); return token::NETWORK; } {address} { yylval->bval = new BDATA; yylval->bval->set( yytext, strlen( yytext ) ); yylval->bval->add( 0, 1 ); return token::ADDRESS; } <> { yyterminate(); } . return token::SEQ; %% /* * PROGRAM * */ bool _IKED::conf_load( const char * path, bool trace ) { // // set some defaults // level = LOG_DEBUG; if( path_conf[ 0 ] == 0 ) snprintf( path_conf, MAX_PATH, "%s/iked.conf", path ); if( path_log[ 0 ] == 0 ) snprintf( path_log, MAX_PATH, "%s/iked.log", PATH_DEBUG ); snprintf( path_dhcp, MAX_PATH, "%s/iked.dhcp", path ); // // open file and run parser // yy_flex_debug = trace; if( !( yyin = fopen( path_conf, "r" ) ) ) { log.txt( LLOG_ERROR, "!! : unable to open %s\n", path_conf ); return false; } log.txt( LOG_INFO, "ii : reading config %s\n", path_conf ); yy::conf_parser parser( *this ); parser.set_debug_level( trace ); parser.parse(); fclose( yyin ); return !conf_fail; } ike-2.2.1+dfsg/source/iked/crypto.cpp000066400000000000000000000610151223036517100174460ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "crypto.h" void crypto_init() { OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); } void crypto_done() { ERR_free_strings(); EVP_cleanup(); CRYPTO_cleanup_all_ex_data(); } static unsigned char group1[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x3A, 0x36, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; static unsigned char group2[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; static unsigned char group5[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x23, 0x73, 0x27, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; static unsigned char group14[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; static unsigned char group15[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; static unsigned char group16[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; static unsigned char group17[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92, 0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26, 0xC1, 0xD4, 0xDC, 0xB2, 0x60, 0x26, 0x46, 0xDE, 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD, 0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E, 0xE5, 0xDB, 0x38, 0x2F, 0x41, 0x30, 0x01, 0xAE, 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31, 0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18, 0xDA, 0x3E, 0xDB, 0xEB, 0xCF, 0x9B, 0x14, 0xED, 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B, 0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B, 0x33, 0x20, 0x51, 0x51, 0x2B, 0xD7, 0xAF, 0x42, 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF, 0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC, 0xF0, 0x32, 0xEA, 0x15, 0xD1, 0x72, 0x1D, 0x03, 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6, 0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82, 0xB5, 0xA8, 0x40, 0x31, 0x90, 0x0B, 0x1C, 0x9E, 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3, 0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE, 0x0F, 0x1D, 0x45, 0xB7, 0xFF, 0x58, 0x5A, 0xC5, 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA, 0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8, 0x14, 0xCC, 0x5E, 0xD2, 0x0F, 0x80, 0x37, 0xE0, 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28, 0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76, 0xF5, 0x50, 0xAA, 0x3D, 0x8A, 0x1F, 0xBF, 0xF0, 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C, 0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, 0x38, 0x7F, 0xE8, 0xD7, 0x6E, 0x3C, 0x04, 0x68, 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE, 0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6, 0xE6, 0x94, 0xF9, 0x1E, 0x6D, 0xCC, 0x40, 0x24, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; static unsigned char group18[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92, 0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26, 0xC1, 0xD4, 0xDC, 0xB2, 0x60, 0x26, 0x46, 0xDE, 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD, 0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E, 0xE5, 0xDB, 0x38, 0x2F, 0x41, 0x30, 0x01, 0xAE, 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31, 0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18, 0xDA, 0x3E, 0xDB, 0xEB, 0xCF, 0x9B, 0x14, 0xED, 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B, 0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B, 0x33, 0x20, 0x51, 0x51, 0x2B, 0xD7, 0xAF, 0x42, 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF, 0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC, 0xF0, 0x32, 0xEA, 0x15, 0xD1, 0x72, 0x1D, 0x03, 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6, 0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82, 0xB5, 0xA8, 0x40, 0x31, 0x90, 0x0B, 0x1C, 0x9E, 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3, 0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE, 0x0F, 0x1D, 0x45, 0xB7, 0xFF, 0x58, 0x5A, 0xC5, 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA, 0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8, 0x14, 0xCC, 0x5E, 0xD2, 0x0F, 0x80, 0x37, 0xE0, 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28, 0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76, 0xF5, 0x50, 0xAA, 0x3D, 0x8A, 0x1F, 0xBF, 0xF0, 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C, 0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, 0x38, 0x7F, 0xE8, 0xD7, 0x6E, 0x3C, 0x04, 0x68, 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE, 0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6, 0xE6, 0x94, 0xF9, 0x1E, 0x6D, 0xBE, 0x11, 0x59, 0x74, 0xA3, 0x92, 0x6F, 0x12, 0xFE, 0xE5, 0xE4, 0x38, 0x77, 0x7C, 0xB6, 0xA9, 0x32, 0xDF, 0x8C, 0xD8, 0xBE, 0xC4, 0xD0, 0x73, 0xB9, 0x31, 0xBA, 0x3B, 0xC8, 0x32, 0xB6, 0x8D, 0x9D, 0xD3, 0x00, 0x74, 0x1F, 0xA7, 0xBF, 0x8A, 0xFC, 0x47, 0xED, 0x25, 0x76, 0xF6, 0x93, 0x6B, 0xA4, 0x24, 0x66, 0x3A, 0xAB, 0x63, 0x9C, 0x5A, 0xE4, 0xF5, 0x68, 0x34, 0x23, 0xB4, 0x74, 0x2B, 0xF1, 0xC9, 0x78, 0x23, 0x8F, 0x16, 0xCB, 0xE3, 0x9D, 0x65, 0x2D, 0xE3, 0xFD, 0xB8, 0xBE, 0xFC, 0x84, 0x8A, 0xD9, 0x22, 0x22, 0x2E, 0x04, 0xA4, 0x03, 0x7C, 0x07, 0x13, 0xEB, 0x57, 0xA8, 0x1A, 0x23, 0xF0, 0xC7, 0x34, 0x73, 0xFC, 0x64, 0x6C, 0xEA, 0x30, 0x6B, 0x4B, 0xCB, 0xC8, 0x86, 0x2F, 0x83, 0x85, 0xDD, 0xFA, 0x9D, 0x4B, 0x7F, 0xA2, 0xC0, 0x87, 0xE8, 0x79, 0x68, 0x33, 0x03, 0xED, 0x5B, 0xDD, 0x3A, 0x06, 0x2B, 0x3C, 0xF5, 0xB3, 0xA2, 0x78, 0xA6, 0x6D, 0x2A, 0x13, 0xF8, 0x3F, 0x44, 0xF8, 0x2D, 0xDF, 0x31, 0x0E, 0xE0, 0x74, 0xAB, 0x6A, 0x36, 0x45, 0x97, 0xE8, 0x99, 0xA0, 0x25, 0x5D, 0xC1, 0x64, 0xF3, 0x1C, 0xC5, 0x08, 0x46, 0x85, 0x1D, 0xF9, 0xAB, 0x48, 0x19, 0x5D, 0xED, 0x7E, 0xA1, 0xB1, 0xD5, 0x10, 0xBD, 0x7E, 0xE7, 0x4D, 0x73, 0xFA, 0xF3, 0x6B, 0xC3, 0x1E, 0xCF, 0xA2, 0x68, 0x35, 0x90, 0x46, 0xF4, 0xEB, 0x87, 0x9F, 0x92, 0x40, 0x09, 0x43, 0x8B, 0x48, 0x1C, 0x6C, 0xD7, 0x88, 0x9A, 0x00, 0x2E, 0xD5, 0xEE, 0x38, 0x2B, 0xC9, 0x19, 0x0D, 0xA6, 0xFC, 0x02, 0x6E, 0x47, 0x95, 0x58, 0xE4, 0x47, 0x56, 0x77, 0xE9, 0xAA, 0x9E, 0x30, 0x50, 0xE2, 0x76, 0x56, 0x94, 0xDF, 0xC8, 0x1F, 0x56, 0xE8, 0x80, 0xB9, 0x6E, 0x71, 0x60, 0xC9, 0x80, 0xDD, 0x98, 0xED, 0xD3, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; bool dh_init( long group, DH ** dh_data, long * dh_size ) { DH * dh = DH_new(); if( dh == NULL ) return false; dh->p = NULL; dh->g = NULL; dh->length = 0; // // set p ( prime ) value // unsigned char * p_data = NULL; size_t p_size = 0; dh->p = BN_new(); if( dh->p == NULL ) goto dh_failed; switch( group ) { case 1: if( !BN_bin2bn( group1, sizeof( group1 ), dh->p ) ) goto dh_failed; break; case 2: if( !BN_bin2bn( group2, sizeof( group2 ), dh->p ) ) goto dh_failed; break; case 5: if( !BN_bin2bn( group5, sizeof( group5 ), dh->p ) ) goto dh_failed; break; case 14: if( !BN_bin2bn( group14, sizeof( group14 ), dh->p ) ) goto dh_failed; break; case 15: if( !BN_bin2bn( group15, sizeof( group15 ), dh->p ) ) goto dh_failed; break; case 16: if( !BN_bin2bn( group16, sizeof( group16 ), dh->p ) ) goto dh_failed; break; case 17: if( !BN_bin2bn( group17, sizeof( group17 ), dh->p ) ) goto dh_failed; break; case 18: if( !BN_bin2bn( group18, sizeof( group18 ), dh->p ) ) goto dh_failed; break; default: goto dh_failed; } // // set g ( generator ) value // dh->g = BN_new(); if( dh->g == NULL ) goto dh_failed; if( !BN_set_word( dh->g, 2 ) ) goto dh_failed; // // generate private and public DH values // if( !DH_generate_key( dh ) ) goto dh_failed; *dh_data = dh; *dh_size = BN_num_bytes( dh->p ); return true; dh_failed: DH_free( dh ); return false; } ike-2.2.1+dfsg/source/iked/crypto.h000066400000000000000000000047331223036517100171170ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #ifndef _CRYPTO_H_ #define _CRYPTO_H_ #include "openssl/dh.h" #include "openssl/evp.h" #include "openssl/md5.h" #include "openssl/hmac.h" #include "openssl/pem.h" #include "openssl/pkcs12.h" #include "openssl/err.h" #include "openssl/rand.h" void crypto_init(); void crypto_done(); bool dh_init( long group, DH ** dh_data, long * dh_size ); #endif ike-2.2.1+dfsg/source/iked/dhcp.cpp000066400000000000000000000362511223036517100170500ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "iked.h" long _IKED::socket_dhcp_create( IDB_TUNNEL * tunnel ) { // // only initialize once // if( tunnel->dhcp_sock != INVALID_SOCKET ) return LIBIKE_OK; // // create dhcp transaction id // rand_bytes( &tunnel->dhcp_xid, 4 ); // // create dhcp hw address id // uint32_t peer_addr = tunnel->saddr_r.saddr4.sin_addr.s_addr; tunnel->dhcp_hwaddr[ 0 ] = 0x40; // locally administered unicast MAC tunnel->dhcp_hwaddr[ 1 ] = dhcp_seed[ 1 ]; tunnel->dhcp_hwaddr[ 2 ] = dhcp_seed[ 2 ] ^ ( ( peer_addr >> 0 ) & 0xff ); tunnel->dhcp_hwaddr[ 3 ] = dhcp_seed[ 3 ] ^ ( ( peer_addr >> 8 ) & 0xff ); tunnel->dhcp_hwaddr[ 4 ] = dhcp_seed[ 4 ] ^ ( ( peer_addr >> 16 ) & 0xff ); tunnel->dhcp_hwaddr[ 5 ] = dhcp_seed[ 5 ] ^ ( ( peer_addr >> 24 ) & 0xff ); // // create dhcp socket // tunnel->dhcp_sock = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP ); if( tunnel->dhcp_sock == INVALID_SOCKET ) { log.txt( LLOG_ERROR, "!! : failed to create DHCP socket\n" ); return LIBIKE_SOCKET; } // // bind socket to address and port // struct sockaddr_in saddr = tunnel->saddr_l.saddr4; saddr.sin_port = htons( UDP_PORT_DHCPS ); if( bind( tunnel->dhcp_sock, ( sockaddr * ) &saddr, sizeof( saddr ) ) < 0 ) { log.txt( LLOG_ERROR, "!! : failed to bind DHCP socket\n" ); return LIBIKE_SOCKET; } // // set non-blocking operation // #ifdef WIN32 u_long arg = 1; if( ioctlsocket( tunnel->dhcp_sock, FIONBIO, &arg ) < 0 ) { log.txt( LLOG_ERROR, "!! : failed to set DHCP socket to non-blocking\n" ); return LIBIKE_SOCKET; } #else if( fcntl( tunnel->dhcp_sock, F_SETFL, O_NONBLOCK ) < 0 ) { log.txt( LLOG_ERROR, "!! : failed to set DHCP socket to non-blocking\n" ); return LIBIKE_SOCKET; } #endif char txtaddr[ LIBIKE_MAX_TEXTADDR ]; text_addr( txtaddr, saddr.sin_addr ); log.txt( LLOG_DEBUG, "ii : setup DHCP socket for address %s\n", txtaddr ); // // create dhcp ipsec policies // policy_dhcp_create( tunnel ); // // add tunnel dhcp event // tunnel->inc( true ); tunnel->event_dhcp.delay = 1000; ith_timer.add( &tunnel->event_dhcp ); return LIBIKE_OK; } long _IKED::socket_dhcp_remove( IDB_TUNNEL * tunnel ) { // // remove dhcp ipsec policies // policy_dhcp_remove( tunnel ); // // close dhcp socket // if( tunnel->dhcp_sock != INVALID_SOCKET ) { #ifdef WIN32 closesocket( tunnel->dhcp_sock ); #else close( tunnel->dhcp_sock ); #endif tunnel->dhcp_sock = INVALID_SOCKET; } return LIBIKE_OK; } long _IKED::socket_dhcp_send( IDB_TUNNEL * tunnel, PACKET & packet ) { // // send the packet // struct sockaddr_in saddr = tunnel->saddr_r.saddr4; saddr.sin_port = htons( UDP_PORT_DHCPS ); int rslt; rslt = sendto( tunnel->dhcp_sock, packet.text(), packet.size(), 0, ( sockaddr * ) &saddr, sizeof( saddr ) ); if( rslt < 0 ) { log.txt( LLOG_ERROR, "!! : failed to write to DHCP socket\n" ); return LIBIKE_SOCKET; } return LIBIKE_OK; } long _IKED::socket_dhcp_recv( IDB_TUNNEL * tunnel, PACKET & packet ) { char buff[ 1024 ]; long size = 1024; size = recv( tunnel->dhcp_sock, buff, size, 0 ); if( size < 0 ) return LIBIKE_NODATA; packet.add( buff, size ); return LIBIKE_OK; } long _IKED::process_dhcp_send( IDB_TUNNEL * tunnel ) { // // DHCP over IPsec discover packet // if( !( tunnel->tstate & TSTATE_VNET_CONFIG ) ) { // // alternate hardware types for // non-rfc conformant gateways // if( tunnel->event_dhcp.retry & 1 ) tunnel->dhcp_hwtype = BOOTP_HW_EHTERNET; else tunnel->dhcp_hwtype = BOOTP_HW_IPSEC; // // create dhcp discover packet // PACKET packet; DHCP_HEADER dhcp_head; memset( &dhcp_head, 0, sizeof( dhcp_head ) ); dhcp_head.magic = DHCP_MAGIC; dhcp_head.op = BOOTP_REQUEST; // bootp request dhcp_head.htype = tunnel->dhcp_hwtype; // bootp hardware type dhcp_head.hlen = 6; // hardware address length dhcp_head.xid = tunnel->dhcp_xid; // transaction id dhcp_head.hops = 1; // router IP ( fake relay ) dhcp_head.giaddr = // ... tunnel->saddr_l.saddr4.sin_addr.s_addr; memcpy( // local hardware address id dhcp_head.chaddr, // ... tunnel->dhcp_hwaddr, 6 ); // ... packet.add( &dhcp_head, sizeof( dhcp_head ) ); packet.add_byte( DHCP_OPT_MSGTYPE ); // message type packet.add_byte( 1 ); // opt size packet.add_byte( DHCP_MSG_DISCOVER ); // message type value packet.add_byte( DHCP_OPT_CLIENTID ); // message type packet.add_byte( 7 ); // opt size packet.add_byte( tunnel->dhcp_hwtype ); // client hw type packet.add( dhcp_head.chaddr, 6 ); // client id value packet.add_byte( DHCP_OPT_END ); // // send the packet // tunnel->event_dhcp.retry++; log.txt( LLOG_DEBUG, "ii : sending DHCP over IPsec discover\n" ); socket_dhcp_send( tunnel, packet ); } // // DHCP over IPsec request packet // if( tunnel->tstate & TSTATE_VNET_CONFIG ) { // // create dhcp request packet // PACKET packet; DHCP_HEADER dhcp_head; memset( &dhcp_head, 0, sizeof( dhcp_head ) ); dhcp_head.magic = DHCP_MAGIC; dhcp_head.op = BOOTP_REQUEST; // bootp request dhcp_head.htype = tunnel->dhcp_hwtype; // bootp hardware type dhcp_head.hlen = 6; // hardware address length dhcp_head.xid = tunnel->dhcp_xid; // transaction id dhcp_head.hops = 1; // router IP ( fake relay ) dhcp_head.giaddr = // ... tunnel->saddr_l.saddr4.sin_addr.s_addr; memcpy( // local hardware address id dhcp_head.chaddr, // ... tunnel->dhcp_hwaddr, 6 ); // ... packet.add( &dhcp_head, sizeof( dhcp_head ) ); packet.add_byte( DHCP_OPT_MSGTYPE ); // message type packet.add_byte( 1 ); // opt size packet.add_byte( DHCP_MSG_REQUEST ); // message type value packet.add_byte( DHCP_OPT_SERVER ); // server id packet.add_byte( 4 ); // opt size packet.add( &tunnel->xconf.dhcp, 4 ); // server id value packet.add_byte( DHCP_OPT_ADDRESS ); // requested address packet.add_byte( 4 ); // opt size packet.add( &tunnel->xconf.addr, 4 ); // address value packet.add_byte( DHCP_OPT_CLIENTID ); // client id packet.add_byte( 7 ); // opt size packet.add_byte( BOOTP_HW_IPSEC ); // client hw type packet.add( dhcp_head.chaddr, 6 ); // client id value packet.add_byte( DHCP_OPT_END ); // // send the packet // tunnel->event_dhcp.retry++; log.txt( LLOG_DEBUG, "ii : sending DHCP over IPsec request\n" ); socket_dhcp_send( tunnel, packet ); } return LIBIKE_OK; } long _IKED::process_dhcp_recv( IDB_TUNNEL * tunnel ) { PACKET packet; long result = socket_dhcp_recv( tunnel, packet ); if( result != LIBIKE_OK ) return LIBIKE_FAILED; // // examine the dhcp reply header // DHCP_HEADER dhcp_head; if( !packet.get( &dhcp_head, sizeof( dhcp_head ) ) ) { log.txt( LLOG_ERROR, "!! : malformed DHCP reply packet\n" ); tunnel->dec( true ); return LIBIKE_FAILED; } if( ( dhcp_head.op != BOOTP_REPLY ) || // bootp reply ( dhcp_head.hlen != 6 ) || // hardware address length ( dhcp_head.magic != DHCP_MAGIC ) ) // magic cookie { log.txt( LLOG_ERROR, "!! : invalid DHCP reply parameters\n" ); tunnel->dec( true ); return LIBIKE_FAILED; } if( ( dhcp_head.htype != BOOTP_HW_EHTERNET ) && // bootp hardware type ( dhcp_head.htype != BOOTP_HW_IPSEC ) ) { log.txt( LLOG_ERROR, "!! : invalid DHCP reply hardware type\n" ); tunnel->dec( true ); return LIBIKE_FAILED; } // // respond to the solicited type // tunnel->dhcp_hwtype = dhcp_head.htype; // // examine the dhcp reply options // log.txt( LLOG_DEBUG, "ii : reading DHCP reply options\n" ); IKE_XCONF config; memset( &config, 0, sizeof( config ) ); uint8_t type; char txtaddr[ LIBIKE_MAX_TEXTADDR ]; bool end = false; while( !end ) { unsigned char opt; unsigned char len; if( !packet.get_byte( opt ) ) break; if( !packet.get_byte( len ) ) break; if( len > ( packet.size() - packet.oset() ) ) break; switch( opt ) { case DHCP_OPT_MSGTYPE: { config.addr.s_addr = dhcp_head.yiaddr; config.opts |= IPSEC_OPTS_ADDR; packet.get_byte( type ); text_addr( txtaddr, config.addr ); switch( type ) { case DHCP_MSG_OFFER: log.txt( LLOG_DEBUG, "ii : - message type = offer ( %s )\n", txtaddr ); break; case DHCP_MSG_ACK: log.txt( LLOG_DEBUG, "ii : - message type = ack ( %s )\n", txtaddr ); break; default: log.txt( LLOG_ERROR, "!! : invalid DHCP message type ( %i )\n", int( type ) ); tunnel->dec( true ); return LIBIKE_FAILED; } break; } case DHCP_OPT_SUBMASK: if( len >= 4 ) { packet.get( &config.mask, 4 ); len -= 4; text_addr( txtaddr, config.mask ); log.txt( LLOG_DEBUG, "ii : - IP4 Netmask = %s\n", txtaddr ); config.opts |= IPSEC_OPTS_MASK; } packet.get_null( len ); break; case DHCP_OPT_SERVER: if( len >= 4 ) { packet.get( &config.dhcp, 4 ); len -= 4; text_addr( txtaddr, config.dhcp ); log.txt( LLOG_DEBUG, "ii : - IP4 DHCP Server = %s\n", txtaddr ); } packet.get_null( len ); break; case DHCP_OPT_LEASE: if( len >= 4 ) { uint32_t d, h, m, s; packet.get_quad( s, true ); tunnel->event_dhcp.lease = s; len -= 4; d = s / 86400; s = s % 86400; h = s / 3600; s = s % 3600; m = s / 60; s = s % 60; log.txt( LLOG_DEBUG, "ii : - IP4 DHCP lease = %d days, %d hours, %d mins, %d secs\n", d, h, m, s ); } packet.get_null( len ); break; case DHCP_OPT_DNSS: while( len >= 4 ) { len -= 4; if( config.nscfg.dnss_count <= IPSEC_DNSS_MAX ) { packet.get( &config.nscfg.dnss_list[ config.nscfg.dnss_count ], 4 ); text_addr( txtaddr, config.nscfg.dnss_list[ config.nscfg.dnss_count ] ); config.nscfg.dnss_count++; log.txt( LLOG_DEBUG, "ii : - IP4 DNS Server = %s\n", txtaddr ); } config.opts |= IPSEC_OPTS_DNSS; } packet.get_null( len ); break; case DHCP_OPT_NBNS: while( len >= 4 ) { len -= 4; if( config.nscfg.nbns_count <= IPSEC_NBNS_MAX ) { packet.get( &config.nscfg.nbns_list[ config.nscfg.nbns_count ], 4 ); text_addr( txtaddr, config.nscfg.nbns_list[ config.nscfg.nbns_count ] ); config.nscfg.nbns_count++; log.txt( LLOG_DEBUG, "ii : - IP4 WINS Server = %s\n", txtaddr ); } config.opts |= IPSEC_OPTS_NBNS; } packet.get_null( len ); break; case DHCP_OPT_DOMAIN: { long tmp = len; if( tmp > 255 ) tmp = 255; if( len >= 1 ) { packet.get( config.nscfg.dnss_suffix, tmp ); config.nscfg.dnss_suffix[ tmp ] = 0; log.txt( LLOG_DEBUG, "ii : - DNS Suffix = %s\n", config.nscfg.dnss_suffix ); config.opts |= IPSEC_OPTS_DOMAIN; } packet.get_null( len - tmp ); break; } case DHCP_OPT_CLIENTID: log.txt( LLOG_DEBUG, "ii : - clientid ( %i bytes )\n", len ); packet.get_null( len ); break; case DHCP_OPT_END: end = true; break; default: log.txt( LLOG_DECODE, "ii : - unknown option ( %02x )\n", opt ); packet.get_null( len ); break; } } // // DHCP offer // if( type == DHCP_MSG_OFFER ) { if( !( tunnel->tstate & TSTATE_VNET_CONFIG ) ) { // // accept supported options // tunnel->xconf.dhcp = config.dhcp; tunnel->xconf.opts = tunnel->xconf.rqst & config.opts; if( tunnel->xconf.opts & IPSEC_OPTS_ADDR ) tunnel->xconf.addr = config.addr; if( tunnel->xconf.opts & IPSEC_OPTS_MASK ) tunnel->xconf.mask = config.mask; if( tunnel->xconf.opts & IPSEC_OPTS_DNSS ) { memcpy( tunnel->xconf.nscfg.dnss_list, config.nscfg.dnss_list, sizeof( config.nscfg.dnss_list ) ); tunnel->xconf.nscfg.dnss_count = config.nscfg.dnss_count; } if( tunnel->xconf.opts & IPSEC_OPTS_DOMAIN ) memcpy( tunnel->xconf.nscfg.dnss_suffix, config.nscfg.dnss_suffix, CONF_STRLEN ); if( tunnel->xconf.opts & IPSEC_OPTS_NBNS ) { memcpy( tunnel->xconf.nscfg.nbns_list, config.nscfg.nbns_list, sizeof( config.nscfg.nbns_list ) ); tunnel->xconf.nscfg.nbns_count = config.nscfg.nbns_count; } tunnel->tstate |= TSTATE_VNET_CONFIG; tunnel->ikei->wakeup(); } } // // DHCP acknowledge // if( type == DHCP_MSG_ACK ) { if( tunnel->tstate & TSTATE_VNET_CONFIG ) { // // setup lease times // tunnel->event_dhcp.retry = 0; tunnel->event_dhcp.renew = time( NULL ); tunnel->event_dhcp.renew += tunnel->event_dhcp.lease / 2; tunnel->ikei->wakeup(); } } return LIBIKE_OK; } ike-2.2.1+dfsg/source/iked/ike.cpp000066400000000000000000000320601223036517100166740ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "iked.h" static char encap_ike[] = "IKE"; static char encap_nat[] = "NAT-T:IKE"; long _IKED::packet_ike_send( IDB_PH1 * ph1, IDB_XCH * xch, PACKET_IKE & packet, bool retry ) { // // if we are dumping decrytped ike // packets, we need to build an ip // packet using the un-encrypted // ike payload // if( dump_decrypt ) { PACKET_IP packet_ip_dump; // // store the isakmp flags // unsigned char * data = packet.buff(); unsigned char flags = data[ ISAKMP_FLAGS_OFFSET ]; // // temporarily strip the encrypt flag // data[ ISAKMP_FLAGS_OFFSET ] = flags & ~ISAKMP_FLAG_ENCRYPT; // // create ip dump packet // packet_ike_encap( packet, packet_ip_dump, ph1->tunnel->saddr_l, ph1->tunnel->saddr_r, ph1->tunnel->natt_version ); // // obtain ethernet header // ETH_HEADER ethhdr; header( packet_ip_dump, ethhdr ); // // dump the ike packet // pcap_decrypt.dump( ethhdr, packet_ip_dump ); // // restore the isakmp flags // data[ ISAKMP_FLAGS_OFFSET ] = flags; } // // encrypt the packet if necessary // packet_ike_encrypt( ph1, packet, &xch->iv ); // // clear any old packets associated // with this db object // xch->resend_clear( true, true ); // // estimate the maximum packet size // after ike encapsulation overhead // size_t encap_size = 0; // account for udp header length encap_size += sizeof( UDP_HEADER ); // account for non-esp marker if( ph1->tunnel->natt_version >= IPSEC_NATT_V02 ) encap_size += sizeof( unsigned long ); // // determine if ike fragmentation // will be used on this packet // bool packet_frag = false; size_t packet_left = packet.size(); if( ph1->vendopts_l.flag.frag && ph1->vendopts_r.flag.frag ) if( ( packet_left + encap_size ) > ph1->tunnel->peer->frag_ike_size ) packet_frag = true; // // fragment and send the packet // or just send the packet // if( packet_frag ) { // // calculate the max fragment payload size // size_t frag_max = ph1->tunnel->peer->frag_ike_size - encap_size; size_t frag_sent = packet.size() - packet_left; // // set out initial fragment index // unsigned char frag_index = 1; // // fragment the ike packet by // recursing on this function // while( packet_left > 0 ) { // // send the remaining packet size // as out next fragment size. the // payload handler will adjust to // accomodate the largest size // possible // size_t frag_size = packet_left; // // create ike fragment using the // original ike packet as a source // PACKET_IKE packet_frag; packet_frag.write( ph1->cookies, ISAKMP_PAYLOAD_FRAGMENT, ph1->exchange, 0 ); payload_add_frag( packet_frag, frag_index, packet.buff() + frag_sent, frag_size, frag_max ); packet_frag.done(); // // transmit the packet // packet_ike_xmit( ph1, xch, packet_frag, retry ); // // log the result // log.txt( LLOG_DEBUG, "ii : ike packet fragment #%i sized to %i bytes\n", frag_index, frag_size ); // // decrement sent packet size and // increment fragment index // packet_left -= frag_size; frag_sent += frag_size; frag_index++; } } else { // // transmit the packet // packet_ike_xmit( ph1, xch, packet, retry ); } // // potentially schedule resend // if( retry ) xch->resend_sched( true ); return LIBIKE_OK; } long _IKED::packet_ike_xmit( IDB_PH1 * ph1, IDB_XCH * xch, PACKET_IKE & packet, bool retry ) { // // prepare for log output // char txtaddr_l[ LIBIKE_MAX_TEXTADDR ]; char txtaddr_r[ LIBIKE_MAX_TEXTADDR ]; text_addr( txtaddr_l, &ph1->tunnel->saddr_l, true ); text_addr( txtaddr_r, &ph1->tunnel->saddr_r, true ); char * encap_mode = encap_ike; if( ph1->tunnel->natt_version != IPSEC_NATT_NONE ) encap_mode = encap_nat; // // encapsulate ike packet into UDP/IP packet // PACKET_IP packet_ip; packet_ike_encap( packet, packet_ip, ph1->tunnel->saddr_l, ph1->tunnel->saddr_r, ph1->tunnel->natt_version ); // // log the result // log.bin( LLOG_DEBUG, LLOG_DECODE, packet_ip.buff(), packet_ip.size(), "-> : send %s packet %s -> %s", encap_mode, txtaddr_l, txtaddr_r ); // // send ike packet // ETH_HEADER header; long result = send_ip( packet_ip, &header ); if( result != LIBIKE_OK ) { ph1->status( XCH_STATUS_DEAD, XCH_FAILED_NETWORK, 0 ); xch->status( XCH_STATUS_DEAD, XCH_FAILED_NETWORK, 0 ); return LIBIKE_FAILED; } // // queue packet for resend // xch->resend_queue( packet_ip ); // // dump for encoded packets // if( dump_encrypt ) pcap_encrypt.dump( header, packet_ip ); return LIBIKE_OK; } long _IKED::packet_ike_encap( PACKET_IKE & packet_ike, PACKET_IP & packet_ip, IKE_SADDR & src, IKE_SADDR & dst, long natt ) { PACKET_UDP packet_udp; packet_udp.write( src.saddr4.sin_port, dst.saddr4.sin_port ); if( natt >= IPSEC_NATT_V02 ) packet_udp.add_null( 4 ); packet_udp.add( packet_ike ); packet_udp.done( src.saddr4.sin_addr, dst.saddr4.sin_addr ); packet_ip.write( src.saddr4.sin_addr, dst.saddr4.sin_addr, ident++, PROTO_IP_UDP ); packet_ip.add( packet_udp ); packet_ip.done(); return true; } long _IKED::packet_ike_decrypt( IDB_PH1 * sa, PACKET_IKE & packet, BDATA * iv ) { log.txt( LLOG_INFO, "=< : cookies %08x%08x:%08x%08x\n", htonl( *( long * ) &sa->cookies.i[ 0 ] ), htonl( *( long * ) &sa->cookies.i[ 4 ] ), htonl( *( long * ) &sa->cookies.r[ 0 ] ), htonl( *( long * ) &sa->cookies.r[ 4 ] ) ); log.txt( LLOG_INFO, "=< : message %08x\n", htonl( packet.get_msgid() ) ); // // check if decrypt is required // unsigned char * data = packet.buff(); size_t size = packet.size(); if( !( data[ ISAKMP_FLAGS_OFFSET ] & ISAKMP_FLAG_ENCRYPT ) ) return LIBIKE_OK; log.bin( LLOG_DEBUG, LLOG_DECODE, iv->buff(), iv->size(), "=< : decrypt iv" ); // // temporarily save enough // of the packet to store // as iv data post decrypt // unsigned char iv_data[ HMAC_MAX_MD_CBLOCK ]; memcpy( iv_data, data + size - iv->size(), iv->size() ); // // init cipher key and iv // EVP_CIPHER_CTX ctx_cipher; EVP_CIPHER_CTX_init( &ctx_cipher ); EVP_CipherInit_ex( &ctx_cipher, sa->evp_cipher, NULL, NULL, NULL, 0 ); EVP_CIPHER_CTX_set_key_length( &ctx_cipher, ( int ) sa->key.size() ); EVP_CipherInit_ex( &ctx_cipher, NULL, NULL, sa->key.buff(), iv->buff(), 0 ); // // decrypt all but header // EVP_Cipher( &ctx_cipher, data + sizeof( IKE_HEADER ), data + sizeof( IKE_HEADER ), ( int ) size - sizeof( IKE_HEADER ) ); EVP_CIPHER_CTX_cleanup( &ctx_cipher ); log.bin( LLOG_DEBUG, LLOG_DECODE, data, size, "== : decrypt packet" ); // // validate the packet integrity // IKE_HEADER * header = ( IKE_HEADER * ) packet.buff(); size = sizeof( IKE_HEADER ); if( packet.size() < size ) { log.txt( LLOG_ERROR, "!! : validate packet failed ( truncated header )\n" ); return LIBIKE_FAILED; } while( true ) { IKE_PAYLOAD * payload = ( IKE_PAYLOAD * )( packet.buff() + size ); if( packet.size() < ( size + sizeof( IKE_PAYLOAD ) ) ) { log.txt( LLOG_ERROR, "!! : validate packet failed ( truncated payload )\n" ); return LIBIKE_FAILED; } if( payload->reserved ) { log.txt( LLOG_ERROR, "!! : validate packet failed ( reserved value is non-null )\n" ); return LIBIKE_FAILED; } size += ntohs( payload->length ); if( packet.size() < size ) { log.txt( LLOG_ERROR, "!! : validate packet failed ( payload length is invalid )\n" ); return LIBIKE_FAILED; } if( payload->next == ISAKMP_PAYLOAD_NONE ) break; } // // validate packet padding. if the encrypted // packet size is equal to the ike message // length, we can skip this step. although the // RFC states there should at least be one pad // byte that describes the padding length, if // we are strict we will break compatibility // with many implementations including cisco // if( size < packet.size() ) { // // trim packet padding // size_t diff = packet.size() - size; packet.size( size ); log.txt( LLOG_DEBUG, "<= : trimmed packet padding ( %i bytes )\n", diff ); header = ( IKE_HEADER * ) packet.buff(); header->length = htonl( ( uint32_t ) size ); } // // store cipher iv data // memcpy( iv->buff(), iv_data, iv->size() ); log.bin( LLOG_DEBUG, LLOG_DECODE, iv->buff(), iv->size(), "<= : stored iv" ); return LIBIKE_OK; } long _IKED::packet_ike_encrypt( IDB_PH1 * sa, PACKET_IKE & packet, BDATA * iv ) { log.txt( LLOG_INFO, ">= : cookies %08x%08x:%08x%08x\n", htonl( *( long * ) &sa->cookies.i[ 0 ] ), htonl( *( long * ) &sa->cookies.i[ 4 ] ), htonl( *( long * ) &sa->cookies.r[ 0 ] ), htonl( *( long * ) &sa->cookies.r[ 4 ] ) ); log.txt( LLOG_INFO, ">= : message %08x\n", htonl( packet.get_msgid() ) ); // // check if encrypt is required // unsigned char * data = packet.buff(); size_t size = packet.size(); if( !( data[ ISAKMP_FLAGS_OFFSET ] & ISAKMP_FLAG_ENCRYPT ) ) return LIBIKE_OK; log.bin( LLOG_DEBUG, LLOG_DECODE, iv->buff(), iv->size(), ">= : encrypt iv" ); log.bin( LLOG_DEBUG, LLOG_DECODE, packet.buff(), packet.size(), "== : encrypt packet" ); // // determine pad length // size_t plen = size - sizeof( IKE_HEADER ); size_t blen = EVP_CIPHER_block_size( sa->evp_cipher ); size_t padd = 0; if( plen % blen ) padd += blen - ( plen % blen ); packet.add_null( padd ); data = packet.buff(); size = packet.size(); // // set new packet length in header // IKE_HEADER * header = ( IKE_HEADER * ) packet.buff(); header->length = htonl( ( uint32_t ) size ); // // init cipher key and iv and // encrypt all but header // EVP_CIPHER_CTX ctx_cipher; EVP_CIPHER_CTX_init( &ctx_cipher ); EVP_CipherInit_ex( &ctx_cipher, sa->evp_cipher, NULL, NULL, NULL, 1 ); EVP_CIPHER_CTX_set_key_length( &ctx_cipher, ( int ) sa->key.size() ); EVP_CipherInit_ex( &ctx_cipher, NULL, NULL, sa->key.buff(), iv->buff(), 1 ); EVP_Cipher( &ctx_cipher, data + sizeof( IKE_HEADER ), data + sizeof( IKE_HEADER ), ( int ) size - sizeof( IKE_HEADER ) ); EVP_CIPHER_CTX_cleanup( &ctx_cipher ); // // store cipher iv data // memcpy( iv->buff(), data + size - iv->size(), iv->size() ); log.bin( LLOG_DEBUG, LLOG_DECODE, iv->buff(), iv->size(), "== : stored iv" ); return LIBIKE_OK; } ike-2.2.1+dfsg/source/iked/ike.exch.config.cpp000066400000000000000000001550711223036517100210760ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "iked.h" long _IKED::process_config_recv( IDB_PH1 * ph1, PACKET_IKE & packet, unsigned char payload ) { long result = LIBIKE_OK; // // log packet type // log.txt( LLOG_INFO, "ii : processing config packet ( %i bytes )\n", packet.size() ); // // attempt to locate a known // config for this phase1 // uint32_t msgid = packet.get_msgid(); IDB_CFG * cfg = NULL; if( !idb_list_cfg.find( true, &cfg, ph1 ) ) { // // create new object config object // cfg = new IDB_CFG( ph1, false ); cfg->add( true ); } // // if the msgid has changed, set the // config msgid value and the iv // if( cfg->msgid != msgid ) { cfg->msgid = msgid; cfg->new_msgiv( ph1 ); } // // make sure we are not dealing // with an sa marked for delete // if( ph1->status() == XCH_STATUS_DEAD ) { log.txt( LLOG_ERROR, "!! : config packet ignored ( phase1 marked for death )\n" ); cfg->dec( true ); return LIBIKE_OK; } if( cfg->status() == XCH_STATUS_DEAD ) { log.txt( LLOG_ERROR, "!! : config packet ignored ( config marked for death )\n" ); cfg->dec( true ); return LIBIKE_OK; } // // make sure we are not dealing // whith an imature phase1 sa // if( ph1->status() < XCH_STATUS_MATURE ) { log.txt( LLOG_ERROR, "!! : config packet ignored ( phase1 not mature )\n" ); cfg->dec( true ); return LIBIKE_OK; } // // make sure we are not dealing // with a mature sa // if( cfg->status() >= XCH_STATUS_MATURE ) { log.txt( LLOG_ERROR, "!! : config packet ignored ( config already mature )\n" ); cfg->dec( true ); return LIBIKE_OK; } // // decrypt packet // if( packet_ike_decrypt( ph1, packet, &cfg->iv ) != LIBIKE_OK ) { log.txt( LLOG_ERROR, "!! : config packet ignored ( packet decryption error )\n" ); cfg->dec( true ); return LIBIKE_OK; } // // if we are dumping decrypted packets, // we need to rebuild a full packet to // dump to pcap format // if( dump_decrypt ) { // // strip the isakmp encryption flag // packet.buff()[ ISAKMP_FLAGS_OFFSET ] &= ~ISAKMP_FLAG_ENCRYPT; // // build ip dump packet // PACKET_IP packet_ip_dump; packet_ike_encap( packet, packet_ip_dump, cfg->tunnel->saddr_r, cfg->tunnel->saddr_l, cfg->tunnel->natt_version ); // // obtain ethernet header // ETH_HEADER ethhdr; header( packet_ip_dump, ethhdr ); // // dump the packet // pcap_decrypt.dump( ethhdr, packet_ip_dump ); } // // read and process all payloads // cfg->hda.del(); cfg->attr_reset(); while( payload != ISAKMP_PAYLOAD_NONE ) { // // read the payload header // uint8_t next_payload; if( !packet.get_payload( false, next_payload ) ) break; // // check the payload type // switch( payload ) { // // hash payload // case ISAKMP_PAYLOAD_HASH: { result = payload_get_hash( packet, cfg->hash_r, ph1->hash_size ); cfg->xstate |= XSTATE_RECV_HA; break; } // // attribute payload // case ISAKMP_PAYLOAD_ATTRIB: { size_t beg = packet.oset() - 4; result = payload_get_cfglist( packet, cfg ); size_t end = packet.oset(); cfg->hda.add( packet.buff() + beg, end - beg ); break; } // // unhandled payload // default: log.txt( LLOG_ERROR, "!! : unhandled config payload \'%s\' ( %i )\n", find_name( NAME_PAYLOAD, payload ), payload ); result = LIBIKE_FAILED; break; } // // was the entire payload read // if( packet.get_payload_left() ) log.txt( LLOG_ERROR, "!! : unprocessed payload data !!!\n" ); // // check the result // if( result != LIBIKE_OK ) { // // flag sa for removal // ph1->status( XCH_STATUS_DEAD, XCH_FAILED_MSG_FORMAT, packet.notify ); cfg->dec( true ); return result; } // // read next payload // payload = next_payload; } // // now that all payloads have been read, // validate any received hash values // if( config_chk_hash( ph1, cfg, msgid ) != LIBIKE_OK ) { // // update status and release // ph1->status( XCH_STATUS_DEAD, XCH_FAILED_MSG_AUTH, ISAKMP_N_INVALID_HASH_INFORMATION ); cfg->dec( true ); return LIBIKE_FAILED; } // // hanlde server to client messages // while( ph1->initiator ) { // // handle xauth messages // if( ph1->vendopts_l.flag.xauth ) if( !( cfg->xstate & CSTATE_RECV_XRSLT ) ) if( !config_client_xauth_recv( cfg, ph1 ) ) break; // // handle modecfg pull messages // if( cfg->tunnel->peer->xconf_mode == CONFIG_MODE_PULL ) if( !( cfg->xstate & CSTATE_RECV_XCONF ) ) if( !config_client_xconf_pull_recv( cfg, ph1 ) ) break; // // handle modecfg push messages // if( cfg->tunnel->peer->xconf_mode == CONFIG_MODE_PUSH ) if( !( cfg->xstate & CSTATE_RECV_XCONF ) ) if( !config_client_xconf_push_recv( cfg, ph1 ) ) break; // // unexpected message // break; } // // now build and send any response // packets that may be necessary // if( ( ph1->status() != XCH_STATUS_DEAD ) && ( cfg->status() != XCH_STATUS_MATURE ) ) process_config_send( ph1, cfg ); // // cleanup // cfg->dec( true ); return LIBIKE_OK; } long _IKED::process_config_send( IDB_PH1 * ph1, IDB_CFG * cfg ) { cfg->attr_reset(); // // hanlde server to client messages // while( ph1->initiator ) { // // handle xauth messages // if( ph1->vendopts_l.flag.xauth ) if( !( cfg->xstate & CSTATE_SENT_XRSLT ) ) if( !config_client_xauth_send( cfg, ph1 ) ) break; // // handle modecfg pull messages // if( cfg->tunnel->peer->xconf_mode == CONFIG_MODE_PULL ) if( !( cfg->xstate & CSTATE_SENT_ACK ) ) if( !config_client_xconf_pull_send( cfg, ph1 ) ) break; // // handle modecfg push messages // if( cfg->tunnel->peer->xconf_mode == CONFIG_MODE_PUSH ) if( !( cfg->xstate & CSTATE_SENT_ACK ) ) if( !config_client_xconf_push_send( cfg, ph1 ) ) break; // // handle dhcp over ipsec // if( cfg->tunnel->peer->xconf_mode == CONFIG_MODE_DHCP ) { log.txt( LLOG_INFO, "ii : configuration method is DHCP over IPsec \n" ); socket_dhcp_create( ph1->tunnel ); break; } // // handle manual config // if( ph1->tunnel->peer->xconf_mode == CONFIG_MODE_NONE ) { log.txt( LLOG_INFO, "ii : configuration method is manual\n" ); break; } // // unexpected message // break; } // // if all required operations are // complete, make sure the config // handle is flagged as mature // if( ( cfg->xstate & CSTATE_RECV_XRSLT ) && ( cfg->xstate & CSTATE_SENT_XRSLT ) && ( cfg->xstate & CSTATE_RECV_XCONF ) && ( cfg->xstate & CSTATE_SENT_XCONF ) ) { if( cfg->tunnel->peer->xconf_mode != CONFIG_MODE_DHCP ) { if( !( cfg->tunnel->tstate & TSTATE_VNET_CONFIG ) ) { cfg->tunnel->tstate |= TSTATE_VNET_CONFIG; cfg->tunnel->ikei->wakeup(); } } cfg->status( XCH_STATUS_MATURE, XCH_NORMAL, 0 ); cfg->resend_clear( true, false ); } return LIBIKE_OK; } bool _IKED::config_client_xauth_recv( IDB_CFG * cfg, IDB_PH1 * ph1 ) { // // expecting xauth request // if( cfg->mtype == ISAKMP_CFG_REQUEST ) { // // if we have have previously received a // comlete xauth request, authentication // failed and the gateway is prompting // us for an alternate user & password // if( ( cfg->xstate & CSTATE_RECV_XUSER ) && ( cfg->xstate & CSTATE_RECV_XPASS ) ) { log.txt( LLOG_ERROR, "!! : duplicate xauth request, authentication failed\n" ); ph1->status( XCH_STATUS_DEAD, XCH_FAILED_USER_AUTH, 0 ); return false; } // // read the request attributes // cfg->tunnel->xauth.type = XAUTH_TYPE_GENERIC; BDATA message; long count = cfg->attr_count(); long index = 0; for( ; index < count; index++ ) { IKE_ATTR * attr = cfg->attr_get( index ); switch( attr->atype ) { case XAUTH_TYPE: case CHKPT_TYPE: if( attr->basic ) cfg->tunnel->xauth.type = attr->bdata; log.txt( LLOG_INFO, "ii : - xauth authentication type\n" ); break; case XAUTH_USER_NAME: case CHKPT_USER_NAME: cfg->xstate |= CSTATE_RECV_XUSER; log.txt( LLOG_INFO, "ii : - xauth username\n" ); break; case XAUTH_USER_PASSWORD: case CHKPT_USER_PASSWORD: cfg->xstate |= CSTATE_RECV_XPASS; log.txt( LLOG_INFO, "ii : - xauth password\n" ); break; case XAUTH_PASSCODE: cfg->xstate |= CSTATE_RECV_XPASS | CSTATE_USE_PASSCODE; log.txt( LLOG_INFO, "ii : - xauth passcode\n" ); break; case XAUTH_CHALLENGE: case CHKPT_CHALLENGE: cfg->xstate |= CSTATE_RECV_XPASS; log.txt( LLOG_INFO, "ii : - xauth challenge\n" ); if( !attr->basic ) cfg->tunnel->xauth.hash = attr->vdata; break; case XAUTH_MESSAGE: case CHKPT_MESSAGE: if( !attr->basic ) message.add( attr->vdata ); break; default: log.txt( LLOG_INFO, "ww : unhandled xauth attribute %i\n", attr->atype ); break; } } message.add( 0, 1 ); // // examine the xauth request // switch( cfg->tunnel->xauth.type ) { case XAUTH_TYPE_GENERIC: log.txt( LLOG_INFO, "ii : received basic xauth request - %s\n", message.text() ); break; case XAUTH_TYPE_RADIUS_CHAP: log.txt( LLOG_INFO, "ii : received chap xauth request - %s\n", message.text() ); break; default: log.txt( LLOG_ERROR, "!! : received unhandled xauth request type\n" ); ph1->status( XCH_STATUS_DEAD, XCH_FAILED_MSG_FORMAT, 0 ); break; } return false; } // // expecting xauth response // if( cfg->mtype == ISAKMP_CFG_SET ) { // // read the result attributes // BDATA message; long count = cfg->attr_count(); long index = 0; long status = -1; for( ; index < count; index++ ) { IKE_ATTR * attr = cfg->attr_get( index ); switch( attr->atype ) { case XAUTH_STATUS: case CHKPT_STATUS: if( attr->basic ) status = attr->bdata; break; case XAUTH_MESSAGE: case CHKPT_MESSAGE: if( !attr->basic ) message.add( attr->vdata ); break; } } message.add( 0, 1 ); // // make sure we received a status value // if( status == -1 ) { // // some gateways will send a config push // message before an xauth response. in // this case, call the correct handler // if( cfg->tunnel->peer->xconf_mode == CONFIG_MODE_PUSH ) return config_client_xconf_push_recv( cfg, ph1 ); log.txt( LLOG_ERROR, "!! : no xauth status received and config mode is not push\n" ); ph1->status( XCH_STATUS_DEAD, XCH_FAILED_MSG_FORMAT, 0 ); return false; } // // examine the xauth result // log.txt( LLOG_INFO, "ii : received xauth result - %s\n", message.text() ); BDATA user; user = cfg->tunnel->xauth.user; user.add( 0, 1 ); if( status == 1 ) { log.txt( LLOG_INFO, "ii : user %s authentication succeeded\n", user.text() ); } else { log.txt( LLOG_ERROR, "!! : user %s authentication failed\n", user.text() ); ph1->status( XCH_STATUS_DEAD, XCH_FAILED_USER_AUTH, 0 ); } // // NOTE : we set the username and password // as already sent and received in case the // gateway bypasses xauth on rekey // cfg->xstate |= CSTATE_SENT_XUSER; cfg->xstate |= CSTATE_SENT_XPASS; cfg->xstate |= CSTATE_RECV_XUSER; cfg->xstate |= CSTATE_RECV_XPASS; cfg->xstate |= CSTATE_RECV_XRSLT; return false; } // // unhandled message type // log.txt( LLOG_ERROR, "!! : config message type is invalid for xauth\n" ); ph1->status( XCH_STATUS_DEAD, XCH_FAILED_MSG_FORMAT, 0 ); return false; } bool _IKED::config_client_xauth_send( IDB_CFG * cfg, IDB_PH1 * ph1 ) { if( !( cfg->xstate & CSTATE_SENT_XUSER ) || !( cfg->xstate & CSTATE_SENT_XPASS ) ) { cfg->mtype = ISAKMP_CFG_REPLY; if( !ph1->vendopts_r.flag.chkpt ) { // // standard xauth processing // cfg->attr_add_b( XAUTH_TYPE, cfg->tunnel->xauth.type ); if( ( cfg->xstate & CSTATE_RECV_XUSER ) && !( cfg->xstate & CSTATE_SENT_XUSER ) ) { cfg->attr_add_v( XAUTH_USER_NAME, cfg->tunnel->xauth.user.buff(), cfg->tunnel->xauth.user.size() ); cfg->xstate |= CSTATE_SENT_XUSER; log.txt( LLOG_INFO, "ii : - standard xauth username\n" ); } if( ( cfg->xstate & CSTATE_RECV_XPASS ) && !( cfg->xstate & CSTATE_SENT_XPASS ) ) { switch( cfg->tunnel->xauth.type ) { case XAUTH_TYPE_GENERIC: if( !( cfg->xstate & CSTATE_USE_PASSCODE ) ) { cfg->attr_add_v( XAUTH_USER_PASSWORD, cfg->tunnel->xauth.pass.buff(), cfg->tunnel->xauth.pass.size() ); log.txt( LLOG_INFO, "ii : - standard xauth password\n" ); } else { cfg->attr_add_v( XAUTH_PASSCODE, cfg->tunnel->xauth.pass.buff(), cfg->tunnel->xauth.pass.size() ); log.txt( LLOG_INFO, "ii : - standard xauth passcode\n" ); } break; case XAUTH_TYPE_RADIUS_CHAP: { if( !cfg->tunnel->xauth.hash.size() ) { cfg->attr_add_v( XAUTH_USER_PASSWORD, cfg->tunnel->xauth.pass.buff(), cfg->tunnel->xauth.pass.size() ); log.txt( LLOG_INFO, "ii : - standard xauth password ( no chap challenge received )\n" ); } else { uint8_t id; rand_bytes( &id, 1 ); BDATA rslt; rslt.add( &id, sizeof( id ) ); rslt.add( 0, MD5_DIGEST_LENGTH ); MD5_CTX ctx; MD5_Init( &ctx ); MD5_Update( &ctx, &id, sizeof( id ) ); MD5_Update( &ctx, cfg->tunnel->xauth.pass.buff(), cfg->tunnel->xauth.pass.size() ); MD5_Update( &ctx, cfg->tunnel->xauth.hash.buff(), cfg->tunnel->xauth.hash.size() ); MD5_Final( rslt.buff() + sizeof( id ), &ctx ); cfg->attr_add_v( XAUTH_USER_PASSWORD, rslt.buff(), rslt.size() ); log.txt( LLOG_INFO, "ii : - standard xauth chap password\n" ); } break; } } cfg->xstate |= CSTATE_SENT_XPASS; } } else { // // checkpoint xauth processing // cfg->attr_add_b( XAUTH_TYPE, cfg->tunnel->xauth.type ); if( ( cfg->xstate & CSTATE_RECV_XUSER ) && !( cfg->xstate & CSTATE_SENT_XUSER ) ) { cfg->attr_add_v( CHKPT_USER_NAME, cfg->tunnel->xauth.user.buff(), cfg->tunnel->xauth.user.size() ); cfg->xstate |= CSTATE_SENT_XUSER; log.txt( LLOG_INFO, "ii : - checkpoint xauth username\n" ); } if( ( cfg->xstate & CSTATE_RECV_XPASS ) && !( cfg->xstate & CSTATE_SENT_XPASS ) ) { switch( cfg->tunnel->xauth.type ) { case XAUTH_TYPE_GENERIC: { cfg->attr_add_v( CHKPT_USER_PASSWORD, cfg->tunnel->xauth.pass.buff(), cfg->tunnel->xauth.pass.size() ); log.txt( LLOG_INFO, "ii : - checkpoint xauth password\n" ); break; } case XAUTH_TYPE_RADIUS_CHAP: { uint8_t id; rand_bytes( &id, 1 ); BDATA rslt; rslt.add( &id, sizeof( id ) ); rslt.add( 0, MD5_DIGEST_LENGTH ); MD5_CTX ctx; MD5_Init( &ctx ); MD5_Update( &ctx, &id, sizeof( id ) ); MD5_Update( &ctx, cfg->tunnel->xauth.pass.buff(), cfg->tunnel->xauth.pass.size() ); MD5_Update( &ctx, cfg->tunnel->xauth.hash.buff(), cfg->tunnel->xauth.hash.size() ); MD5_Final( rslt.buff() + sizeof( id ), &ctx ); cfg->attr_add_v( CHKPT_USER_PASSWORD, rslt.buff(), rslt.size() ); log.txt( LLOG_INFO, "ii : - checkpoint xauth chap password\n" ); break; } } cfg->xstate |= CSTATE_SENT_XPASS; } } // // send config packet // BDATA user; user = cfg->tunnel->xauth.user; user.add( 0, 1 ); log.txt( LLOG_INFO, "ii : sending xauth response for %s\n", user.buff() ); config_message_send( ph1, cfg ); return false; } if( !( cfg->xstate & CSTATE_SENT_XRSLT ) ) { // // if we have have not yet received an // xauth result message, postpone this // ack until later if( !( cfg->xstate & CSTATE_RECV_XRSLT ) ) return true; cfg->mtype = ISAKMP_CFG_ACK; // // add the status attribute // if( ph1->vendopts_r.flag.chkpt ) cfg->attr_add_b( CHKPT_STATUS, 1 ); // if( !ph1->vendopts_r.flag.chkpt ) // cfg->attr_add_b( XAUTH_STATUS, 1 ); // else // cfg->attr_add_b( CHKPT_STATUS, 1 ); // // send config packet // log.txt( LLOG_INFO, "ii : sending xauth acknowledge\n" ); config_message_send( ph1, cfg ); cfg->xstate |= CSTATE_SENT_XRSLT; return true; } return false; } bool _IKED::config_client_xconf_pull_recv( IDB_CFG * cfg, IDB_PH1 * ph1 ) { // // expecting configuration pull reply // if( cfg->mtype == ISAKMP_CFG_REPLY ) { // // get configuration attributes // log.txt( LLOG_INFO, "ii : received config pull response\n" ); long getbits = 0; config_xconf_get( cfg, getbits, cfg->tunnel->xconf.rqst, ph1->vendopts_r ); // // add negotiated options // cfg->tunnel->xconf.opts |= cfg->tunnel->xconf.rqst & getbits; cfg->xstate |= CSTATE_RECV_XCONF; return false; } // // unhandled message type // log.txt( LLOG_ERROR, "!! : config message type is invalid for pull config\n" ); ph1->status( XCH_STATUS_DEAD, XCH_FAILED_MSG_FORMAT, 0 ); return false; } bool _IKED::config_client_xconf_pull_send( IDB_CFG * cfg, IDB_PH1 * ph1 ) { if( !( cfg->xstate & CSTATE_SENT_XCONF ) ) { // // set configuration attributes // log.txt( LLOG_INFO, "ii : building config attribute list\n" ); cfg->mtype = ISAKMP_CFG_REQUEST; if( ph1->vendopts_r.flag.chkpt ) iked.rand_bytes( &cfg->ident, sizeof( cfg->ident ) ); config_xconf_set( cfg, cfg->tunnel->xconf.rqst, 0xffffffff, ph1->vendopts_r ); if( cfg->attr_count() ) { // // create new msgid and iv // cfg->new_msgid(); cfg->new_msgiv( ph1 ); // // send config packet // log.txt( LLOG_INFO, "ii : sending config pull request\n" ); config_message_send( ph1, cfg ); cfg->xstate |= CSTATE_SENT_XCONF; } else { // // config not required // log.txt( LLOG_INFO, "ii : config pull is not required\n" ); cfg->xstate |= CSTATE_SENT_XCONF; cfg->xstate |= CSTATE_RECV_XCONF; } return false; } return false; } bool _IKED::config_client_xconf_push_recv( IDB_CFG * cfg, IDB_PH1 * ph1 ) { // // expecting configuration push request // if( cfg->mtype == ISAKMP_CFG_SET ) { // // get xconf attributes // log.txt( LLOG_INFO, "ii : received config push request\n" ); long getbits = 0; config_xconf_get( cfg, getbits, cfg->tunnel->xconf.rqst, ph1->vendopts_r ); // // add negotiated options // cfg->tunnel->xconf.opts |= cfg->tunnel->xconf.rqst & getbits; // // config is now mature // cfg->xstate |= CSTATE_RECV_XCONF; return false; } // // unhandled message type // log.txt( LLOG_ERROR, "!! : config message type is invalid for push config\n" ); ph1->status( XCH_STATUS_DEAD, XCH_FAILED_MSG_FORMAT, 0 ); return false; } bool _IKED::config_client_xconf_push_send( IDB_CFG * cfg, IDB_PH1 * ph1 ) { if( !( cfg->xstate & CSTATE_SENT_XCONF ) ) { // // set xconf attributes // log.txt( LLOG_INFO, "ii : building config attribute list\n" ); cfg->mtype = ISAKMP_CFG_ACK; config_xconf_set( cfg, cfg->tunnel->xconf.rqst, 0xffffffff, ph1->vendopts_r ); // // send config packet // log.txt( LLOG_INFO, "ii : sending config push acknowledge\n" ); config_message_send( ph1, cfg ); cfg->xstate |= CSTATE_SENT_XCONF; return false; } return false; } bool _IKED::config_server_xauth_recv( IDB_CFG * cfg, IDB_PH1 * ph1 ) { if( cfg->mtype == ISAKMP_CFG_REPLY ) { log.txt( LLOG_INFO, "ii : received xauth response\n" ); // // make sure we at least have // user and password attribs // long count = cfg->attr_count(); long index = 0; for( ; index < count; index++ ) { IKE_ATTR * attr = cfg->attr_get( index ); switch( attr->atype ) { case XAUTH_USER_NAME: cfg->xstate |= CSTATE_RECV_XUSER; cfg->tunnel->xauth.user.set( attr->vdata ); break; case XAUTH_USER_PASSWORD: cfg->xstate |= CSTATE_RECV_XPASS; cfg->tunnel->xauth.pass.set( attr->vdata ); break; } } if( !cfg->tunnel->xauth.user.size() ) log.txt( LLOG_ERROR, "!! : missing required username attribute\n" ); if( !cfg->tunnel->xauth.pass.size() ) log.txt( LLOG_ERROR, "!! : missing required password attribute\n" ); return false; } if( cfg->mtype == ISAKMP_CFG_ACK ) { log.txt( LLOG_INFO, "ii : received xauth ack\n" ); cfg->xstate |= CSTATE_RECV_XRSLT; if( cfg->tunnel->peer->xconf_mode != CONFIG_MODE_PUSH ) cfg->status( XCH_STATUS_MATURE, XCH_NORMAL, 0 ); return false; } return false; } bool _IKED::config_server_xauth_send( IDB_CFG * cfg, IDB_PH1 * ph1 ) { if( !( cfg->xstate & CSTATE_SENT_XUSER ) ) { // // set request attributes // cfg->mtype = ISAKMP_CFG_REQUEST; cfg->attr_add_b( XAUTH_TYPE, XAUTH_TYPE_GENERIC ); cfg->attr_add_v( XAUTH_USER_NAME, NULL, 0 ); cfg->attr_add_v( XAUTH_USER_PASSWORD, NULL, 0 ); // // create new msgid and iv // cfg->new_msgid(); cfg->new_msgiv( ph1 ); // // send config packet // config_message_send( ph1, cfg ); // // flag as sent // cfg->xstate |= CSTATE_SENT_XUSER; cfg->xstate |= CSTATE_SENT_XPASS; log.txt( LLOG_INFO, "ii : sent xauth request\n" ); return false; } if( !( cfg->xstate & CSTATE_SENT_XRSLT ) ) { bool allow = false; if( cfg->tunnel->xauth.user.size() && cfg->tunnel->xauth.pass.size() ) allow = true; // // check user password // if( allow ) { cfg->tunnel->xauth.user.add( 0, 1 ); cfg->tunnel->xauth.pass.add( 0, 1 ); allow = cfg->tunnel->peer->xauth_source->auth_pwd( cfg->tunnel->xauth ); if( allow ) iked.log.txt( LLOG_INFO, "ii : xauth user %s password accepted ( %s )\n", cfg->tunnel->xauth.user.text(), cfg->tunnel->peer->xauth_source->name() ); else iked.log.txt( LLOG_ERROR, "!! : xauth user %s password rejected ( %s )\n", cfg->tunnel->xauth.user.text(), cfg->tunnel->peer->xauth_source->name() ); } // // check user group membership // if( allow && cfg->tunnel->peer->xauth_group.size() ) { allow = cfg->tunnel->peer->xauth_source->auth_grp( cfg->tunnel->xauth, cfg->tunnel->peer->xauth_group ); if( allow ) log.txt( LLOG_INFO, "ii : xauth user %s group %s membership accepted ( %s )\n", cfg->tunnel->xauth.user.text(), cfg->tunnel->peer->xauth_group.text(), cfg->tunnel->peer->xauth_source->name() ); else log.txt( LLOG_ERROR, "!! : xauth user %s group %s membership rejected ( %s )\n", cfg->tunnel->xauth.user.text(), cfg->tunnel->peer->xauth_group.text(), cfg->tunnel->peer->xauth_source->name() ); } // // set result attributes // cfg->mtype = ISAKMP_CFG_SET; if( allow ) cfg->attr_add_b( XAUTH_STATUS, 1 ); else cfg->attr_add_b( XAUTH_STATUS, 0 ); // // create new msgid and iv // cfg->new_msgid(); cfg->new_msgiv( ph1 ); // // send config packet // config_message_send( ph1, cfg ); // // flag as sent and release // cfg->xstate |= CSTATE_SENT_XRSLT; log.txt( LLOG_INFO, "ii : sent xauth result\n" ); if( !allow ) ph1->status( XCH_STATUS_DEAD, XCH_FAILED_USER_AUTH, 0 ); return false; } return false; } bool _IKED::config_server_xconf_pull_recv( IDB_CFG * cfg, IDB_PH1 * ph1 ) { if( cfg->mtype == ISAKMP_CFG_REQUEST ) { // // get xconf attributes // log.txt( LLOG_INFO, "ii : received config pull request\n" ); config_xconf_get( cfg, cfg->tunnel->xconf.rqst, 0, ph1->vendopts_r ); cfg->xstate |= CSTATE_RECV_XCONF; return false; } return false; } bool _IKED::config_server_xconf_pull_send( IDB_CFG * cfg, IDB_PH1 * ph1 ) { if( !( cfg->xstate & CSTATE_SENT_XCONF ) ) { // // obtain the client xconf config // cfg->tunnel->peer->xconf_source->rslt( cfg->tunnel ); // // if we are to generate a policy // list during config, do this now // if( cfg->tunnel->peer->plcy_mode == POLICY_MODE_CONFIG ) policy_list_create( cfg->tunnel, false ); if( cfg->tunnel->peer->plcy_mode != POLICY_MODE_DISABLE ) cfg->tunnel->xconf.opts |= IPSEC_OPTS_SPLITNET; // // set result attributes // cfg->mtype = ISAKMP_CFG_REPLY; log.txt( LLOG_INFO, "ii : building config attribute list\n" ); config_xconf_set( cfg, cfg->tunnel->xconf.opts, 0, ph1->vendopts_r ); // // send config packet // log.txt( LLOG_INFO, "ii : sending config pull response\n" ); config_message_send( ph1, cfg ); // // flag as sent // cfg->tunnel->tstate |= CSTATE_SENT_XCONF; return false; } return false; } bool _IKED::config_server_xconf_push_recv( IDB_CFG * cfg, IDB_PH1 * ph1 ) { if( cfg->mtype == ISAKMP_CFG_ACK ) { // // get xconf attributes // log.txt( LLOG_INFO, "ii : received config push acknowledge\n" ); long readmask = 0; config_xconf_get( cfg, readmask, 0, ph1->vendopts_r ); cfg->xstate |= CSTATE_RECV_XCONF; return false; } return false; } bool _IKED::config_server_xconf_push_send( IDB_CFG * cfg, IDB_PH1 * ph1 ) { if( !( cfg->xstate & CSTATE_SENT_XCONF ) ) { // // in push mode the client doesnt // request its desired attributes // cfg->tunnel->xconf.rqst = cfg->tunnel->peer->xconf_source->config.opts; // // obtain the client xconf config // cfg->tunnel->peer->xconf_source->rslt( cfg->tunnel ); // // if we are to generate a policy // list during config, do this now // if( cfg->tunnel->peer->plcy_mode == POLICY_MODE_CONFIG ) policy_list_create( cfg->tunnel, false ); if( cfg->tunnel->peer->plcy_mode != POLICY_MODE_DISABLE ) cfg->tunnel->xconf.opts |= IPSEC_OPTS_SPLITNET; // // set attributes // cfg->mtype = ISAKMP_CFG_SET; log.txt( LLOG_INFO, "ii : building config attribute list\n" ); config_xconf_set( cfg, cfg->tunnel->xconf.opts, 0, ph1->vendopts_r ); // // create new msgid and iv // cfg->new_msgid(); cfg->new_msgiv( ph1 ); // // send config packet // log.txt( LLOG_INFO, "ii : sending config push request\n" ); config_message_send( ph1, cfg ); cfg->attr_reset(); // // flag as sent // cfg->xstate |= CSTATE_SENT_XCONF; return false; } return false; } long _IKED::config_xconf_set( IDB_CFG * cfg, long setbits, long setmask, VENDOPTS vendopts ) { // // the modecfg draft defines valid lengths // for most attribute values. a checkpoint // client always submits 4 null bytes even // for values that are not constrained to // 0 or 4 byte lengths. we mimic this odd // behavior for compatibility sake. // void * null_ptr = NULL; char null_len = 0; char null_val[ 4 ] = { 0 }; if( vendopts.flag.chkpt ) { null_ptr = null_val; null_len = 4; } // // standard attributes // if( setbits & IPSEC_OPTS_ADDR ) { if( setmask & IPSEC_OPTS_ADDR ) { cfg->attr_add_v( INTERNAL_IP4_ADDRESS, null_ptr, null_len ); log.txt( LLOG_DEBUG, "ii : - IP4 Address\n" ); cfg->attr_add_v( INTERNAL_ADDRESS_EXPIRY, null_ptr, null_len ); log.txt( LLOG_DEBUG, "ii : - Address Expiry\n" ); } else { cfg->attr_add_v( INTERNAL_IP4_ADDRESS, &cfg->tunnel->xconf.addr, sizeof( cfg->tunnel->xconf.addr ) ); char txtaddr[ LIBIKE_MAX_TEXTADDR ]; text_addr( txtaddr, cfg->tunnel->xconf.addr ); log.txt( LLOG_DEBUG, "ii : - IP4 Address = %s\n", txtaddr ); cfg->attr_add_v( INTERNAL_ADDRESS_EXPIRY, &cfg->tunnel->xconf.expi, sizeof( cfg->tunnel->xconf.expi ) ); log.txt( LLOG_DEBUG, "ii : - Address Expiry = %i secs\n", cfg->tunnel->xconf.expi ); } } if( setbits & IPSEC_OPTS_MASK ) { if( setmask & IPSEC_OPTS_MASK ) { cfg->attr_add_v( INTERNAL_IP4_NETMASK, null_ptr, null_len ); log.txt( LLOG_DEBUG, "ii : - IP4 Netmask\n" ); } else { cfg->attr_add_v( INTERNAL_IP4_NETMASK, &cfg->tunnel->xconf.mask, sizeof( cfg->tunnel->xconf.mask ) ); char txtaddr[ LIBIKE_MAX_TEXTADDR ]; text_addr( txtaddr, cfg->tunnel->xconf.mask ); log.txt( LLOG_DEBUG, "ii : - IP4 Netmask = %s\n", txtaddr ); } } if( setbits & IPSEC_OPTS_DNSS ) { if( setmask & IPSEC_OPTS_DNSS ) { cfg->attr_add_v( INTERNAL_IP4_DNS, null_ptr, null_len ); log.txt( LLOG_DEBUG, "ii : - IP4 DNS Server\n" ); } else { uint32_t index = 0; uint32_t count = cfg->tunnel->xconf.nscfg.dnss_count; for( ; index < count; index++ ) { cfg->attr_add_v( INTERNAL_IP4_DNS, &cfg->tunnel->xconf.nscfg.dnss_list[ index ], 4 ); char txtaddr[ LIBIKE_MAX_TEXTADDR ]; text_addr( txtaddr, cfg->tunnel->xconf.nscfg.dnss_list[ index ] ); log.txt( LLOG_DEBUG, "ii : - IP4 DNS Server = %s\n", txtaddr ); } } } if( setbits & IPSEC_OPTS_NBNS ) { if( setmask & IPSEC_OPTS_NBNS ) { cfg->attr_add_v( INTERNAL_IP4_NBNS, null_ptr, null_len ); log.txt( LLOG_DEBUG, "ii : - IP4 WINS Server\n" ); } else { uint32_t index = 0; uint32_t count = cfg->tunnel->xconf.nscfg.nbns_count; for( ; index < count; index++ ) { cfg->attr_add_v( INTERNAL_IP4_NBNS, &cfg->tunnel->xconf.nscfg.nbns_list[ index ], 4 ); char txtaddr[ LIBIKE_MAX_TEXTADDR ]; text_addr( txtaddr, cfg->tunnel->xconf.nscfg.nbns_list[ index ] ); log.txt( LLOG_DEBUG, "ii : - IP4 WINS Server = %s\n", txtaddr ); } } } // // non cisco unity attributes // if( !vendopts.flag.unity ) { if( setbits & IPSEC_OPTS_SPLITNET ) { if( setmask & IPSEC_OPTS_SPLITNET ) { cfg->attr_add_v( INTERNAL_IP4_SUBNET, NULL, 0 ); log.txt( LLOG_DEBUG, "ii : - IP4 Subnet\n" ); } else { IKE_PH2ID ph2id; long index = 0; while( cfg->tunnel->idlist_incl.get( ph2id, index++ ) ) { IKE_SUBNET subnet; memset( &subnet, 0, sizeof( subnet ) ); subnet.addr = ph2id.addr1; subnet.mask = ph2id.addr2; char txtid[ LIBIKE_MAX_TEXTP2ID ]; text_ph2id( txtid, &ph2id ); if( subnet.addr.s_addr && subnet.mask.s_addr ) { cfg->attr_add_v( INTERNAL_IP4_SUBNET, &subnet, sizeof( subnet ) ); log.txt( LLOG_DEBUG, "ii : - IP4 Subnet = %s\n", txtid ); } else { log.txt( LLOG_DEBUG, "ii : - IP4 Subnet = %s\n ( invalid subnet ignored )", txtid ); } } } } } // // cisco unity attributes // if( vendopts.flag.unity ) { if( setbits & IPSEC_OPTS_DOMAIN ) { if( setmask & IPSEC_OPTS_DOMAIN ) { cfg->attr_add_v( UNITY_DEF_DOMAIN, NULL, 0 ); log.txt( LLOG_DEBUG, "ii : - DNS Suffix\n" ); } else { cfg->attr_add_v( UNITY_DEF_DOMAIN, &cfg->tunnel->xconf.nscfg.dnss_suffix, strlen( cfg->tunnel->xconf.nscfg.dnss_suffix ) ); log.txt( LLOG_DEBUG, "ii : - DNS Suffix = %s\n", cfg->tunnel->xconf.nscfg.dnss_suffix ); } } if( setbits & IPSEC_OPTS_SPLITDNS ) { if( setmask & IPSEC_OPTS_SPLITDNS ) { cfg->attr_add_v( UNITY_SPLIT_DOMAIN, NULL, 0 ); log.txt( LLOG_DEBUG, "ii : - Split DNS Domain\n" ); } else { BDATA domain; long index = 0; while( cfg->tunnel->domains.get( domain, index++ ) ) { log.txt( LLOG_DEBUG, "ii : - Split DNS Domain = %s\n", domain.text() ); if( index > 1 ) domain.ins( ',', 1 ); cfg->attr_add_v( UNITY_SPLIT_DOMAIN, domain.buff(), domain.size() ); } } } if( setbits & IPSEC_OPTS_SPLITNET ) { if( setmask & IPSEC_OPTS_SPLITNET ) { cfg->attr_add_v( UNITY_SPLIT_INCLUDE, NULL, 0 ); cfg->attr_add_v( UNITY_SPLIT_EXCLUDE, NULL, 0 ); log.txt( LLOG_DEBUG, "ii : - IP4 Split Network Include\n" "ii : - IP4 Split Network Exclude\n" ); } else { IKE_PH2ID ph2id; long index = 0; while( cfg->tunnel->idlist_incl.get( ph2id, index++ ) ) { IKE_UNITY_NET unity_net; memset( &unity_net, 0, sizeof( unity_net ) ); unity_net.prot = ph2id.prot; unity_net.addr = ph2id.addr1; unity_net.mask = ph2id.addr2; unity_net.port_rmt = ph2id.port; char txtid[ LIBIKE_MAX_TEXTP2ID ]; text_ph2id( txtid, &ph2id ); if( unity_net.addr.s_addr && unity_net.mask.s_addr ) { cfg->attr_add_v( UNITY_SPLIT_INCLUDE, &unity_net, sizeof( unity_net ) ); log.txt( LLOG_DEBUG, "ii : - IP4 Split Network Include = %s\n", txtid ); } else { log.txt( LLOG_DEBUG, "ii : - IP4 Split Network Include = %s\n ( invalid subnet ignored )", txtid ); } } index = 0; while( cfg->tunnel->idlist_excl.get( ph2id, index++ ) ) { IKE_UNITY_NET unity_net; memset( &unity_net, 0, sizeof( unity_net ) ); unity_net.prot = ph2id.prot; unity_net.addr = ph2id.addr1; unity_net.mask = ph2id.addr2; unity_net.port_rmt = ph2id.port; char txtid[ LIBIKE_MAX_TEXTP2ID ]; text_ph2id( txtid, &ph2id ); if( unity_net.addr.s_addr && unity_net.mask.s_addr ) { cfg->attr_add_v( UNITY_SPLIT_EXCLUDE, &unity_net, sizeof( unity_net ) ); log.txt( LLOG_DEBUG, "ii : - IP4 Split Network Exclude = %s\n", txtid ); } else { log.txt( LLOG_DEBUG, "ii : - IP4 Split Network Exclude = %s\n ( invalid subnet ignored )", txtid ); } } } } if( setbits & IPSEC_OPTS_BANNER ) { if( setmask & IPSEC_OPTS_BANNER ) { cfg->attr_add_v( UNITY_BANNER, NULL, 0 ); log.txt( LLOG_DEBUG, "ii : - Login Banner\n" ); } else { cfg->attr_add_v( UNITY_BANNER, cfg->tunnel->banner.buff(), cfg->tunnel->banner.size() ); cfg->tunnel->banner.add( 0, 1 ); log.txt( LLOG_DEBUG, "ii : - Login Banner ( %i bytes )\n", cfg->tunnel->banner.size() ); } } if( setbits & IPSEC_OPTS_PFS ) { if( setmask & IPSEC_OPTS_PFS ) { cfg->attr_add_v( UNITY_PFS, NULL, 0 ); log.txt( LLOG_DEBUG, "ii : - PFS Group\n" ); } else { cfg->attr_add_b( UNITY_PFS, cfg->tunnel->xconf.dhgr ); log.txt( LLOG_DEBUG, "ii : - PFS Group = %i\n", cfg->tunnel->xconf.dhgr ); } } if( setbits & IPSEC_OPTS_SAVEPW ) { if( setmask & IPSEC_OPTS_SAVEPW ) { cfg->attr_add_v( UNITY_SAVE_PASSWD, NULL, 0 ); log.txt( LLOG_DEBUG, "ii : - Save Password\n" ); } else { cfg->attr_add_b( UNITY_SAVE_PASSWD, cfg->tunnel->xconf.svpw ); log.txt( LLOG_DEBUG, "ii : - Save Password = %i\n", cfg->tunnel->xconf.svpw ); } } if( setbits & IPSEC_OPTS_CISCO_UDP ) { if( setmask & IPSEC_OPTS_CISCO_UDP ) { cfg->attr_add_v( UNITY_NATT_PORT, NULL, 0 ); log.txt( LLOG_DEBUG, "ii : - CISCO UDP Port\n" ); } else { cfg->attr_add_b( UNITY_NATT_PORT, cfg->tunnel->peer->natt_port ); log.txt( LLOG_DEBUG, "ii : - CISCO UDP Port = %i\n", ntohs( cfg->tunnel->peer->natt_port ) ); } } cfg->attr_add_v( APPLICATION_VERSION, UNITY_APP_VERSION_STRING, strlen( UNITY_APP_VERSION_STRING ) ); log.txt( LLOG_DEBUG, "ii : - Application Version = %s\n", UNITY_APP_VERSION_STRING ); cfg->attr_add_v( UNITY_FW_TYPE, unity_fwtype.buff(), unity_fwtype.size() ); log.txt( LLOG_DEBUG, "ii : - Firewall Type = CISCO-UNKNOWN\n" ); } // // checkpoint attributes // if( vendopts.flag.chkpt ) { cfg->attr_add_v( CHKPT_MARCIPAN_REASON_CODE, null_ptr, null_len ); log.txt( LLOG_DEBUG, "ii : - Marcipan Reason Code\n" ); uint8_t macaddr[ 6 ]; rand_bytes( &macaddr, 6 ); cfg->attr_add_v( CHKPT_MAC_ADDRESS, macaddr, 6 ); log.txt( LLOG_DEBUG, "ii : - Adapter MAC Address = %02x:%02x:%02x:%02x:%02x:%02x\n", macaddr[ 0 ], macaddr[ 1 ], macaddr[ 2 ], macaddr[ 3 ], macaddr[ 4 ], macaddr[ 5 ] ); if( setbits & IPSEC_OPTS_DOMAIN ) { if( setmask & IPSEC_OPTS_DOMAIN ) { cfg->attr_add_v( CHKPT_DEF_DOMAIN, null_ptr, null_len ); log.txt( LLOG_DEBUG, "ii : - DNS Suffix\n" ); } else { cfg->attr_add_v( CHKPT_DEF_DOMAIN, &cfg->tunnel->xconf.nscfg.dnss_suffix, strlen( cfg->tunnel->xconf.nscfg.dnss_suffix ) ); log.txt( LLOG_DEBUG, "ii : - DNS Suffix = %s\n", cfg->tunnel->xconf.nscfg.dnss_suffix ); } } } return LIBIKE_OK; } long _IKED::config_xconf_get( IDB_CFG * cfg, long & getbits, long getmask, VENDOPTS vendopts ) { long count = cfg->attr_count(); long index = 0; for( ; index < count; index++ ) { IKE_ATTR * attr = cfg->attr_get( index ); // // standard attributes // bool unhandled = false; switch( attr->atype ) { case INTERNAL_IP4_ADDRESS: { getbits |= IPSEC_OPTS_ADDR; if( ( getmask & IPSEC_OPTS_ADDR ) && attr->vdata.size() ) { if( attr->vdata.size() != 4 ) { log.txt( LLOG_ERROR, "!! : - IP4 Address has invalid size ( %i bytes )\n", attr->vdata.size() ); break; } memcpy( &cfg->tunnel->xconf.addr, attr->vdata.buff(), 4 ); char txtaddr[ LIBIKE_MAX_TEXTADDR ]; text_addr( txtaddr, cfg->tunnel->xconf.addr ); log.txt( LLOG_DEBUG, "ii : - IP4 Address = %s\n", txtaddr ); } else log.txt( LLOG_DEBUG, "ii : - IP4 Address\n" ); break; } case INTERNAL_IP4_NETMASK: { getbits |= IPSEC_OPTS_MASK; if( ( getmask & IPSEC_OPTS_MASK ) && attr->vdata.size() ) { if( attr->vdata.size() != 4 ) { log.txt( LLOG_ERROR, "!! : - IP4 Netmask has invalid size ( %i bytes )\n", attr->vdata.size() ); break; } memcpy( &cfg->tunnel->xconf.mask, attr->vdata.buff(), 4 ); char txtaddr[ LIBIKE_MAX_TEXTADDR ]; text_addr( txtaddr, cfg->tunnel->xconf.mask ); log.txt( LLOG_DEBUG, "ii : - IP4 Netmask = %s\n", txtaddr ); } else log.txt( LLOG_DEBUG, "ii : - IP4 Netmask\n" ); break; } case INTERNAL_IP4_DNS: { getbits |= IPSEC_OPTS_DNSS; if( ( getmask & IPSEC_OPTS_DNSS ) && attr->vdata.size() ) { if( cfg->tunnel->xconf.nscfg.dnss_count < IPSEC_DNSS_MAX ) { if( attr->vdata.size() != 4 ) { log.txt( LLOG_ERROR, "!! : - IP4 DNS Server has invalid size ( %i bytes )\n", attr->vdata.size() ); break; } memcpy( &cfg->tunnel->xconf.nscfg.dnss_list[ cfg->tunnel->xconf.nscfg.dnss_count ], attr->vdata.buff(), 4 ); char txtaddr[ LIBIKE_MAX_TEXTADDR ]; text_addr( txtaddr, cfg->tunnel->xconf.nscfg.dnss_list[ cfg->tunnel->xconf.nscfg.dnss_count ] ); cfg->tunnel->xconf.nscfg.dnss_count++; log.txt( LLOG_DEBUG, "ii : - IP4 DNS Server = %s\n", txtaddr ); } } else log.txt( LLOG_DEBUG, "ii : - IP4 DNS Server\n" ); break; } case INTERNAL_IP4_NBNS: { getbits |= IPSEC_OPTS_NBNS; if( ( getmask & IPSEC_OPTS_NBNS ) && attr->vdata.size() ) { if( cfg->tunnel->xconf.nscfg.nbns_count < IPSEC_NBNS_MAX ) { if( attr->vdata.size() != 4 ) { log.txt( LLOG_ERROR, "!! : - IP4 WINS Server has invalid size ( %i bytes )\n", attr->vdata.size() ); break; } memcpy( &cfg->tunnel->xconf.nscfg.nbns_list[ cfg->tunnel->xconf.nscfg.nbns_count ], attr->vdata.buff(), 4 ); char txtaddr[ LIBIKE_MAX_TEXTADDR ]; text_addr( txtaddr, cfg->tunnel->xconf.nscfg.nbns_list[ cfg->tunnel->xconf.nscfg.nbns_count ] ); cfg->tunnel->xconf.nscfg.nbns_count++; log.txt( LLOG_DEBUG, "ii : - IP4 WINS Server = %s\n", txtaddr ); } } else log.txt( LLOG_DEBUG, "ii : - IP4 WINS Server\n" ); break; } case INTERNAL_ADDRESS_EXPIRY: { getbits |= IPSEC_OPTS_ADDR; if( ( getmask & IPSEC_OPTS_ADDR ) && attr->vdata.size() ) { if( attr->vdata.size() != 4 ) { log.txt( LLOG_ERROR, "!! : - Address Expiry has invalid size ( %i bytes )\n", attr->vdata.size() ); break; } memcpy( &cfg->tunnel->xconf.expi, attr->vdata.buff(), 4 ); log.txt( LLOG_DEBUG, "ii : - Address Expiry = %i\n", cfg->tunnel->xconf.expi ); } else log.txt( LLOG_DEBUG, "ii : - Address Expiry\n" ); break; } case APPLICATION_VERSION: { if( attr->vdata.size() ) { BDATA appver; appver = attr->vdata; appver.add( "", 1 ); log.txt( LLOG_DEBUG, "ii : - Application Version = %s\n", appver.text() ); } else log.txt( LLOG_DEBUG, "ii : - Application Version\n" ); break; } default: unhandled = true; } // // non cisco unity attributes // if( !vendopts.flag.unity && unhandled ) { unhandled = false; switch( attr->atype ) { case INTERNAL_IP4_SUBNET: { getbits |= IPSEC_OPTS_SPLITNET; if( ( getmask & IPSEC_OPTS_SPLITNET ) && attr->vdata.size() ) { int net_count = int( attr->vdata.size() / sizeof( IKE_SUBNET ) ); int net_index = 0; for( ; net_index < net_count; net_index++ ) { long offset = sizeof( IKE_SUBNET ) * net_index; IKE_SUBNET * subnet = ( IKE_SUBNET * ) ( attr->vdata.buff() + offset ); IKE_PH2ID ph2id; memset( &ph2id, 0, sizeof( ph2id ) ); ph2id.type = ISAKMP_ID_IPV4_ADDR_SUBNET; ph2id.addr1 = subnet->addr; ph2id.addr2 = subnet->mask; char txtid[ LIBIKE_MAX_TEXTP2ID ]; text_ph2id( txtid, &ph2id ); if( subnet->addr.s_addr && subnet->mask.s_addr ) { log.txt( LLOG_DEBUG, "ii : - IP4 Subnet = %s\n", txtid ); cfg->tunnel->idlist_incl.add( ph2id ); } else { log.txt( LLOG_DEBUG, "ii : - IP4 Subnet = %s ( invalid subnet ignored )\n", txtid ); } } } else log.txt( LLOG_DEBUG, "ii : - IP4 Subnet\n" ); break; } default: unhandled = true; } } // // cisco unity attributes // if( vendopts.flag.unity && unhandled ) { unhandled = false; switch( attr->atype ) { case UNITY_DEF_DOMAIN: { getbits |= IPSEC_OPTS_DOMAIN; if( ( getmask & IPSEC_OPTS_DOMAIN ) && attr->vdata.size() ) { size_t nlen = attr->vdata.size(); if( nlen > ( CONF_STRLEN - 1 ) ) nlen = ( CONF_STRLEN - 1 ); memcpy( cfg->tunnel->xconf.nscfg.dnss_suffix, attr->vdata.buff(), nlen ); cfg->tunnel->xconf.nscfg.dnss_suffix[ nlen ] = 0; log.txt( LLOG_DEBUG, "ii : - DNS Suffix = %s\n", cfg->tunnel->xconf.nscfg.dnss_suffix ); } else log.txt( LLOG_DEBUG, "ii : - DNS Suffix\n" ); break; } case UNITY_SPLIT_DOMAIN: { getbits |= IPSEC_OPTS_SPLITDNS; if( ( getmask & IPSEC_OPTS_SPLITDNS ) && attr->vdata.size() ) { attr->vdata.add( 0, 1 ); unsigned char * dnsstr = attr->vdata.buff(); size_t dnslen = 0; while( dnslen < ( attr->vdata.size() - 1 ) ) { if( *dnsstr == ',' ) { dnslen += 1; dnsstr += 1; } size_t tmplen = strlen( ( char * ) dnsstr ) + 1; BDATA domain; domain.set( dnsstr, tmplen ); log.txt( LLOG_DEBUG, "ii : - Split Domain = %s\n", dnsstr ); dnslen += tmplen; dnsstr += tmplen; if( getmask & IPSEC_OPTS_SPLITDNS ) cfg->tunnel->domains.add( domain ); } } else log.txt( LLOG_DEBUG, "ii : - Split Domain\n" ); break; } case UNITY_SPLIT_INCLUDE: case UNITY_SPLIT_EXCLUDE: { getbits |= IPSEC_OPTS_SPLITNET; if( ( getmask & IPSEC_OPTS_SPLITNET ) && attr->vdata.size() ) { int net_count = int( attr->vdata.size() / sizeof( IKE_UNITY_NET ) ); int net_index = 0; for( ; net_index < net_count; net_index++ ) { long offset = sizeof( IKE_UNITY_NET ) * net_index; IKE_UNITY_NET * unity_net = ( IKE_UNITY_NET * ) ( attr->vdata.buff() + offset ); IKE_PH2ID ph2id; memset( &ph2id, 0, sizeof( ph2id ) ); ph2id.prot = unity_net->prot; ph2id.type = ISAKMP_ID_IPV4_ADDR_SUBNET; ph2id.addr1 = unity_net->addr; ph2id.addr2 = unity_net->mask; ph2id.port = unity_net->port_rmt; // // FIXME : there is a bug in racoon // that sends bogus protocol and port // information. I have comitted a fix // to ipsec-tools head and 0.7 but we // need to wait for that to settle // before we can remove the next two // lines of code; // ph2id.prot = 0; ph2id.port = 0; char txtid[ LIBIKE_MAX_TEXTP2ID ]; text_ph2id( txtid, &ph2id ); if( attr->atype == UNITY_SPLIT_INCLUDE ) { if( unity_net->addr.s_addr && unity_net->addr.s_addr ) { log.txt( LLOG_DEBUG, "ii : - IP4 Split Network Include = %s\n", txtid ); cfg->tunnel->idlist_incl.add( ph2id ); } else { log.txt( LLOG_DEBUG, "ii : - IP4 Split Network Include = %s ( invalid subnet ignored )\n", txtid ); } } else { if( unity_net->addr.s_addr && unity_net->addr.s_addr ) { log.txt( LLOG_DEBUG, "ii : - IP4 Split Network Exclude = %s\n", txtid ); cfg->tunnel->idlist_excl.add( ph2id ); } else { log.txt( LLOG_DEBUG, "ii : - IP4 Split Network Exclude = %s ( invalid subnet ignored )\n", txtid ); } } } } else { if( attr->atype == UNITY_SPLIT_INCLUDE ) log.txt( LLOG_DEBUG, "ii : - IP4 Split Network Include\n" ); if( attr->atype == UNITY_SPLIT_EXCLUDE ) log.txt( LLOG_DEBUG, "ii : - IP4 Split Network Exclude\n" ); } break; } case UNITY_BANNER: { getbits |= IPSEC_OPTS_BANNER; if( ( getmask & IPSEC_OPTS_BANNER ) && attr->vdata.size() ) { cfg->tunnel->banner.add( 0, 1 ); size_t size = 15; char text[ 16 ] = { 0 }; if( size > attr->vdata.size() ) size = attr->vdata.size(); memcpy( text, attr->vdata.buff(), size ); log.txt( LLOG_DEBUG, "ii : - Login Banner = %s ...\n", text ); cfg->tunnel->banner.set( attr->vdata ); cfg->tunnel->banner.add( 0, 1 ); } else log.txt( LLOG_DEBUG, "ii : - Login Banner\n" ); break; } case UNITY_PFS: { getbits |= IPSEC_OPTS_PFS; if( ( getmask & IPSEC_OPTS_PFS ) && attr->basic ) { log.txt( LLOG_DEBUG, "ii : - PFS Group = %d\n", attr->bdata ); cfg->tunnel->xconf.dhgr = attr->bdata; } else log.txt( LLOG_DEBUG, "ii : - PFS Group\n" ); break; } case UNITY_SAVE_PASSWD: { getbits |= IPSEC_OPTS_SAVEPW; if( ( getmask & IPSEC_OPTS_SAVEPW ) && attr->basic ) { log.txt( LLOG_DEBUG, "ii : - Save Password = %d\n", attr->bdata ); cfg->tunnel->xconf.svpw = attr->bdata; } else log.txt( LLOG_DEBUG, "ii : - Save Password\n" ); break; } case UNITY_NATT_PORT: { getbits |= IPSEC_OPTS_CISCO_UDP; if( ( getmask & IPSEC_OPTS_CISCO_UDP ) && attr->basic ) { log.txt( LLOG_DEBUG, "ii : - Cisco UDP Port = %d\n", attr->bdata ); if( cfg->tunnel->natt_version == IPSEC_NATT_NONE ) { cfg->tunnel->natt_version = IPSEC_NATT_CISCO; cfg->tunnel->peer->natt_port = htons( attr->bdata ); cfg->tunnel->inc( true ); cfg->tunnel->event_natt.delay = cfg->tunnel->peer->natt_rate * 1000; ith_timer.add( &cfg->tunnel->event_natt ); log.txt( LLOG_INFO, "ii : switching nat-t to cisco-udp\n" ); } } else log.txt( LLOG_DEBUG, "ii : - Cisco UDP Port\n" ); break; } case UNITY_FW_TYPE: { if( attr->vdata.size() ) { log.txt( LLOG_DEBUG, "ii : - Firewall Type = %i bytes\n", attr->vdata.size() ); } else log.txt( LLOG_DEBUG, "ii : - Firewall Type\n" ); break; } default: unhandled = true; } } // // unknown attribute type // if( unhandled ) { if( attr->basic ) log.txt( LLOG_DEBUG, "ii : - Unkown BASIC %u = %u\n", attr->atype, attr->bdata ); else log.txt( LLOG_DEBUG, "ii : - Unkown VARIABLE %u = %u bytes\n", attr->atype, attr->vdata.size() ); } } return LIBIKE_OK; } long _IKED::config_chk_hash( IDB_PH1 * ph1, IDB_CFG * cfg, unsigned long msgid ) { BDATA hash_c; hash_c.size( ph1->hash_size ); HMAC_CTX ctx_prf; HMAC_CTX_init( &ctx_prf ); HMAC_Init_ex( &ctx_prf, ph1->skeyid_a.buff(), ( int ) ph1->skeyid_a.size(), ph1->evp_hash, NULL ); HMAC_Update( &ctx_prf, ( unsigned char * ) &msgid, 4 ); HMAC_Update( &ctx_prf, cfg->hda.buff(), cfg->hda.size() ); HMAC_Final( &ctx_prf, hash_c.buff(), NULL ); HMAC_CTX_cleanup( &ctx_prf ); log.bin( LLOG_DEBUG, LLOG_DECODE, cfg->hash_r.buff(), cfg->hash_r.size(), "== : configure hash_i ( computed )" ); log.bin( LLOG_DEBUG, LLOG_DECODE, hash_c.buff(), hash_c.size(), "== : configure hash_c ( computed )" ); if( cfg->hash_r != hash_c ) { log.txt( LLOG_ERROR, "!! : configure hash verification failed\n" ); return LIBIKE_FAILED; } log.txt( LLOG_DEBUG, "ii : configure hash verified\n" ); return LIBIKE_OK; } long _IKED::config_message_send( IDB_PH1 * ph1, IDB_CFG * cfg ) { // // create config exchange packet // BDATA hash; hash.size( ph1->hash_size ); PACKET_IKE packet; packet.set_msgid( cfg->msgid ); packet.write( ph1->cookies, ISAKMP_PAYLOAD_HASH, ISAKMP_EXCH_CONFIG, ISAKMP_FLAG_ENCRYPT ); size_t off = packet.size(); payload_add_hash( packet, hash, ISAKMP_PAYLOAD_ATTRIB ); size_t beg = packet.size(); payload_add_cfglist( packet, cfg, ISAKMP_PAYLOAD_NONE ); size_t end = packet.size(); packet.done(); // // create message authentication hash // HMAC_CTX ctx_prf; HMAC_CTX_init( &ctx_prf ); HMAC_Init_ex( &ctx_prf, ph1->skeyid_a.buff(), ( int ) ph1->skeyid_a.size(), ph1->evp_hash, NULL ); HMAC_Update( &ctx_prf, ( unsigned char * ) &cfg->msgid, sizeof( cfg->msgid ) ); HMAC_Update( &ctx_prf, packet.buff() + beg, end - beg ); HMAC_Final( &ctx_prf, hash.buff(), 0 ); HMAC_CTX_cleanup( &ctx_prf ); memcpy( packet.buff() + off + 4, hash.buff(), hash.size() ); log.bin( LLOG_DEBUG, LLOG_DECODE, hash.buff(), hash.size(), "== : new configure hash" ); packet_ike_send( ph1, cfg, packet, true ); return LIBIKE_OK; } ike-2.2.1+dfsg/source/iked/ike.exch.inform.cpp000066400000000000000000000634451223036517100211260ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "iked.h" long _IKED::process_inform_send( IDB_PH1 * ph1, IDB_XCH * inform ) { // // sanity checks // assert( ph1 != NULL ); assert( inform->notifications.count() != 0 ); // // create notification packet // PACKET_IKE packet; packet.set_msgid( inform->msgid ); // // determine encryption // unsigned char flags = 0; if( ph1->status() >= XCH_STATUS_MATURE ) flags |= ISAKMP_FLAG_ENCRYPT; // // determine next payload // IKE_NOTIFY notify; inform->notifications.get( notify, 0 ); unsigned char next; if( flags & ISAKMP_FLAG_ENCRYPT ) next = ISAKMP_PAYLOAD_HASH; else next = notify.type; // // write packet header // packet.write( ph1->cookies, next, ISAKMP_EXCH_INFORMATIONAL, flags ); // // optionally add null hash payload // size_t off = packet.size(); if( flags & ISAKMP_FLAG_ENCRYPT ) { inform->hash_l.size( ph1->hash_size ); payload_add_hash( packet, inform->hash_l, notify.type ); } // // add all notify / delete payloads // size_t beg = packet.size(); long nindex = 0; while( 1 ) { // // get next notification // if( !inform->notifications.get( notify, nindex++ ) ) break; // // determine following notification // next = ISAKMP_PAYLOAD_NONE; if( inform->notifications.count() > nindex ) { IKE_NOTIFY next_notify; inform->notifications.get( next_notify, nindex ); next = next_notify.type; } // // add notification payload // switch( notify.type ) { case ISAKMP_PAYLOAD_NOTIFY: payload_add_notify( packet, ¬ify, next ); break; case ISAKMP_PAYLOAD_DELETE: payload_add_delete( packet, ¬ify, next ); break; } } size_t end = packet.size(); inform->hda.add( packet.buff() + beg, end - beg ); // // end packet // packet.done(); // // optionaly build crypto iv // if( flags & ISAKMP_FLAG_ENCRYPT ) { inform_gen_hash( ph1, inform ); memcpy( packet.buff() + off + 4, inform->hash_l.buff(), inform->hash_l.size() ); inform->new_msgiv( ph1 ); } // // send the packet // return packet_ike_send( ph1, inform, packet, false ); } long _IKED::process_inform_recv( IDB_PH1 * ph1, PACKET_IKE & packet, unsigned char payload ) { IDB_INF inform; bool secure = false; long result = LIBIKE_OK; // // log packet type // log.txt( LLOG_INFO, "ii : processing informational packet ( %i bytes )\n", packet.size() ); // // calculate iv for this // informational exchange // inform.msgid = packet.get_msgid(); inform.new_msgiv( ph1 ); // // decrypt packet // if( packet_ike_decrypt( ph1, packet, &inform.iv ) != LIBIKE_OK ) { log.txt( LLOG_ERROR, "!! : informational packet ignored ( packet decryption error )\n" ); return LIBIKE_OK; } // // if we are dumping decrypted packets, // we need to rebuild a full packet to // dump to pcap format // if( dump_decrypt ) { // // strip the isakmp encryption flag // packet.buff()[ ISAKMP_FLAGS_OFFSET ] &= ~ISAKMP_FLAG_ENCRYPT; // // build ip dump packet // PACKET_IP packet_ip_dump; packet_ike_encap( packet, packet_ip_dump, ph1->tunnel->saddr_r, ph1->tunnel->saddr_l, ph1->tunnel->natt_version ); // // obtain ethernet header // ETH_HEADER ethhdr; header( packet_ip_dump, ethhdr ); // // dump the packet // pcap_decrypt.dump( ethhdr, packet_ip_dump ); } // // read and process all payloads // while( payload != ISAKMP_PAYLOAD_NONE ) { // // read the payload header // uint8_t next_payload; if( !packet.get_payload( false, next_payload ) ) break; // // check the payload type // switch( payload ) { // // hash payload // case ISAKMP_PAYLOAD_HASH: { result = payload_get_hash( packet, inform.hash_r, ph1->hash_size ); inform.xstate |= XSTATE_RECV_HA; break; } // // notify payload // case ISAKMP_PAYLOAD_NOTIFY: { IKE_NOTIFY notify; size_t beg = packet.oset() - 4; result = payload_get_notify( packet, ¬ify ); size_t end = packet.oset(); inform.hda.set( packet.buff() + beg, end - beg ); if( result == LIBIKE_OK ) inform.notifications.add( notify ); break; } // // delete payload // case ISAKMP_PAYLOAD_DELETE: { IKE_NOTIFY notify; size_t beg = packet.oset() - 4; result = payload_get_delete( packet, ¬ify ); size_t end = packet.oset(); inform.hda.set( packet.buff() + beg, end - beg ); if( result == LIBIKE_OK ) inform.notifications.add( notify ); break; } // // unhandled payload // default: log.txt( LLOG_ERROR, "!! : unhandled informational payload \'%s\' ( %i )\n", find_name( NAME_PAYLOAD, payload ), payload ); result = LIBIKE_FAILED; break; } // // was the entire payload read // if( packet.get_payload_left() ) log.txt( LLOG_ERROR, "!! : unprocessed payload data !!!\n" ); // // check the result // if( result != LIBIKE_OK ) return result; // // read next payload // payload = next_payload; } // // now that all payloads have been read, // validate any received hash values // if( inform.xstate & XSTATE_RECV_HA ) if( inform_chk_hash( ph1, &inform ) ) secure = true; // // check all notification payloads // if( inform.notifications.count() ) { IKE_NOTIFY notify; long nindex = 0; while( inform.notifications.get( notify, nindex++ ) ) { switch( notify.type ) { case ISAKMP_PAYLOAD_NOTIFY: inform_chk_notify( ph1, ¬ify, secure ); break; case ISAKMP_PAYLOAD_DELETE: inform_chk_delete( ph1, ¬ify, secure ); break; } } } return LIBIKE_OK; } long _IKED::inform_chk_hash( IDB_PH1 * ph1, IDB_XCH * inform ) { BDATA hash_c; hash_c.size( ph1->hash_size ); HMAC_CTX ctx_prf; HMAC_CTX_init( &ctx_prf ); HMAC_Init_ex( &ctx_prf, ph1->skeyid_a.buff(), ( int ) ph1->skeyid_a.size(), ph1->evp_hash, NULL ); HMAC_Update( &ctx_prf, ( unsigned char * ) &inform->msgid, 4 ); HMAC_Update( &ctx_prf, inform->hda.buff(), inform->hda.size() ); HMAC_Final( &ctx_prf, hash_c.buff(), NULL ); HMAC_CTX_cleanup( &ctx_prf ); log.bin( LLOG_DEBUG, LLOG_DECODE, hash_c.buff(), hash_c.size(), "== : informational hash_i ( computed )" ); log.bin( LLOG_DEBUG, LLOG_DECODE, inform->hash_r.buff(), inform->hash_r.size(), "== : informational hash_c ( received )" ); if( inform->hash_r != hash_c ) { log.txt( LLOG_ERROR, "!! : informational hash verification failed\n" ); return LIBIKE_FAILED; } log.txt( LLOG_DEBUG, "ii : informational hash verified\n" ); return LIBIKE_OK; } long _IKED::inform_gen_hash( IDB_PH1 * ph1, IDB_XCH * inform ) { inform->hash_l.size( ph1->hash_size ); HMAC_CTX ctx_prf; HMAC_CTX_init( &ctx_prf ); HMAC_Init_ex( &ctx_prf, ph1->skeyid_a.buff(), ( int ) ph1->skeyid_a.size(), ph1->evp_hash, NULL ); HMAC_Update( &ctx_prf, ( unsigned char * ) &inform->msgid, sizeof( inform->msgid ) ); HMAC_Update( &ctx_prf, inform->hda.buff(), inform->hda.size() ); HMAC_Final( &ctx_prf, inform->hash_l.buff(), 0 ); HMAC_CTX_cleanup( &ctx_prf ); log.bin( LLOG_DEBUG, LLOG_DECODE, inform->hash_l.buff(), inform->hash_l.size(), "== : new informational hash" ); return LIBIKE_OK; } long _IKED::inform_get_spi( char * text, IDB_PH1 * ph1, IKE_NOTIFY * notify ) { switch( notify->spi.size ) { case 0: sprintf_s( text, LIBIKE_MAX_TEXTSPI, "none" ); break; case ( ISAKMP_COOKIE_SIZE * 2 ): sprintf_s( text, LIBIKE_MAX_TEXTSPI, "%08x%08x:%08x%08x", htonl( *( long * ) ¬ify->spi.cookies.i[ 0 ] ), htonl( *( long * ) ¬ify->spi.cookies.i[ 4 ] ), htonl( *( long * ) ¬ify->spi.cookies.r[ 0 ] ), htonl( *( long * ) ¬ify->spi.cookies.r[ 4 ] ) ); break; case ISAKMP_SPI_SIZE: sprintf_s( text, LIBIKE_MAX_TEXTSPI, "0x%08x", ntohl( notify->spi.spi ) ); break; case ISAKMP_CPI_SIZE: sprintf_s( text, LIBIKE_MAX_TEXTSPI, "0x%04x", ntohs( notify->spi.cpi ) ); break; default: sprintf_s( text, LIBIKE_MAX_TEXTSPI, "unspecified value" ); return LIBIKE_FAILED; } return LIBIKE_OK; } long _IKED::inform_chk_notify( IDB_PH1 * ph1, IKE_NOTIFY * notify, bool secure ) { assert( ph1 != NULL ); // // build text strings for logging // char txtspi[ LIBIKE_MAX_TEXTSPI ]; char txtaddr_l[ LIBIKE_MAX_TEXTADDR ]; char txtaddr_r[ LIBIKE_MAX_TEXTADDR ]; inform_get_spi( txtspi, ph1, notify ); text_addr( txtaddr_l, &ph1->tunnel->saddr_l, true ); text_addr( txtaddr_r, &ph1->tunnel->saddr_r, true ); // // log the notification // log.txt( LLOG_INFO, "ii : received peer %s notification\n" "ii : - %s -> %s\n" "ii : - %s spi = %s\n" "ii : - data size %i\n", find_name( NAME_NOTIFY, notify->code ), txtaddr_r, txtaddr_l, find_name( NAME_PROTOCOL, notify->proto ), txtspi, notify->data.size() ); // // only process this message if // it came under the protection // of a mature phase1 sa // if( secure ) if( ( ph1->status() <= XCH_STATUS_MATURE ) || ( ph1->status() >= XCH_STATUS_EXPIRING ) ) return LIBIKE_FAILED; // // process the notify message // switch( notify->spi.size ) { // // phase1 notify // case 0: // // NOTE: the Netgear DPD implementation in // badly broken. it sends a protocol type // if ISAKMP and an SPI length of zero. // case ( ISAKMP_COOKIE_SIZE * 2 ): { switch( notify->code ) { // // NOTE : a cisco device working in a high // availability group will send this notify // message when it would like us to migrate // to a different server. // case ISAKMP_N_UNITY_LOAD_BALANCE: { if( notify->data.size() != sizeof( in_addr ) ) { log.txt( LLOG_ERROR, "!! : UNITY-LOAD-BALANCE address data is invalid ( %i bytes )\n", notify->data.size() ); break; } in_addr addr; notify->data.get( &addr, sizeof( addr ) ); char txtaddr[ LIBIKE_MAX_TEXTADDR ]; text_addr( txtaddr, addr ); // // only migrate if we have yet to setup // the tunnel policies and routes // if( ph1->tunnel->tstate & TSTATE_VNET_CONFIG ) { log.txt( LLOG_INFO, "ii : UNITY-LOAD-BALANCE request ignored ( tunnel already mature )\n" ); break; } log.txt( LLOG_INFO, "ii : UNITY-LOAD-BALANCE requested migration to %s\n", txtaddr ); // // create a new phase1 object // IDB_PH1 * ph1_ulb = new IDB_PH1( ph1->tunnel, true, NULL ); ph1_ulb->add( true ); // // flag our existing phase1 object for removal // ph1->inc( true ); ph1->status( XCH_STATUS_DEAD, XCH_NORMAL, 0 ); ph1->dec( true ); // // re-initialize our tunnel state // // NOTE : we should probably find a better way // to handle this. having this code here is a // bit hackish but we cant use a new tunnel as // the admin thread retains a pointer to the // object for its own use. our only option is // to recycle the existing tunnel and peer. // if( iked.ith_timer.del( &ph1->tunnel->event_dhcp ) ) ph1->tunnel->dec( true ); if( iked.ith_timer.del( &ph1->tunnel->event_dpd ) ) ph1->tunnel->dec( true ); if( iked.ith_timer.del( &ph1->tunnel->event_natt ) ) ph1->tunnel->dec( true ); ph1_ulb->tunnel->tstate = 0; ph1_ulb->tunnel->lstate = 0; ph1_ulb->tunnel->natt_version = IPSEC_NATT_NONE; ph1_ulb->tunnel->stats.dpd = false; ph1_ulb->tunnel->stats.frag = false; ph1_ulb->tunnel->stats.natt = IPSEC_NATT_NONE; // // update the peer and tunnel objects to use // the address received in the notify data // ph1_ulb->tunnel->peer->saddr.saddr4.sin_addr = addr; ph1_ulb->tunnel->saddr_r = ph1_ulb->tunnel->peer->saddr; ph1_ulb->tunnel->saddr_l.saddr4.sin_port = htons( 500 ); // // reinitialize our filter // #ifdef WIN32 iked.tunnel_filter_del( ph1_ulb->tunnel ); iked.tunnel_filter_add( ph1_ulb->tunnel, false ); #endif // // initiate new phase1 // process_phase1_send( ph1_ulb ); ph1_ulb->dec( true ); break; } // // NOTE : the Netgear DPD implementation is // badly broken. they send 16 bytes of zero // padding before the 4 byte sequence value. // if we respond with the full 20 bytes sent // to us, the gateway rejects the value. if // we send only the relevent 4 bytes, the // gateway accepts the value. this is likely // related to the absent ISAKMP cookie value // as the null padding is the same length as // an ISAKMP cookie pair. // case ISAKMP_N_DPD_R_U_THERE: { size_t seq_size = sizeof( ph1->tunnel->event_dpd.sequence ); size_t seq_padd = notify->data.size() - seq_size; if( notify->data.size() < seq_size ) { log.txt( LLOG_ERROR, "!! : DPD ARE-YOU-THERE sequence data is invalid ( %i bytes )\n", notify->data.size() ); break; } uint32_t sequence; notify->data.oset( seq_padd ); notify->data.get( &sequence, sizeof( sequence ) ); if( seq_padd ) { notify->data.del(); notify->data.add( &sequence, sizeof( sequence ) ); } inform_new_notify( ph1, NULL, ISAKMP_N_DPD_R_U_THERE_ACK, ¬ify->data ); sequence = ntohl( sequence ); log.txt( LLOG_DEBUG, "ii : DPD ARE-YOU-THERE sequence %08x returned\n", sequence ); break; } case ISAKMP_N_DPD_R_U_THERE_ACK: { size_t seq_size = sizeof( ph1->tunnel->event_dpd.sequence ); size_t seq_padd = notify->data.size() - seq_size; if( notify->data.size() < seq_size ) { log.txt( LLOG_ERROR, "!! : DPD ARE-YOU-THERE-ACK sequence data is invalid ( %i bytes )\n", notify->data.size() ); break; } // // obtain sequence number and // convert to host byte order // uint32_t sequence; notify->data.oset( seq_padd ); notify->data.get( &sequence, sizeof( sequence ) ); // // check dpd sequence number // sequence = ntohl( sequence ); if( sequence != ph1->tunnel->event_dpd.sequence ) { log.txt( LLOG_ERROR, "!! : DPD ARE-YOU-THERE-ACK sequence %08x rejected\n", sequence ); break; } // // setup the next dpd cycle // log.txt( LLOG_DEBUG, "ii : DPD ARE-YOU-THERE-ACK sequence %08x accepted\n", sequence ); ph1->tunnel->event_dpd.next(); break; } } break; } // // phase2 notify // case ISAKMP_SPI_SIZE: { switch( notify->code ) { case ISAKMP_N_RESPONDER_LIFETIME: { // // attempt to locate phase2 sa // and adjust its lifetime // unsigned long lsecs = 0; unsigned long ldata = 0; unsigned short ltype; IDB_PH2 * ph2_notify; if( idb_list_ph2.find( true, &ph2_notify, ph1->tunnel, XCH_STATUS_ANY, XCH_STATUS_DEAD, NULL, NULL, NULL, ¬ify->spi ) ) { // // create a temp packet for parsing // PACKET_IKE packet; packet.add( notify->data ); // // read all attributes // IKE_ATTR attrib; while( payload_get_attr( packet, attrib ) == LIBIKE_OK ) { switch( attrib.atype ) { case ISAKMP_ATTR_LIFE_TYPE: { if( ( attrib.bdata != IKE_LIFE_TYPE_SECONDS ) && ( attrib.bdata != IKE_LIFE_TYPE_KBYTES ) ) break; ltype = attrib.bdata; break; } case ISAKMP_ATTR_LIFE_DURATION: { unsigned long lval; if( attrib.vdata.size() != sizeof( lval ) ) break; memcpy( &lval, attrib.vdata.buff(), attrib.vdata.size() ); lval = ntohl( lval ); switch( ltype ) { case ISAKMP_LIFETYPE_SECONDS: lsecs = lval; break; case ISAKMP_LIFETYPE_KBYTES: ldata = lval; break; } break; } } } if( lsecs ) { log.txt( LLOG_INFO, "ii : adjusted phase2 sa lifetime to %i seconds\n", lsecs ); IKE_PROPOSAL * proposal_l; IKE_PROPOSAL * proposal_r; long pindex = 0; while( ph2_notify->plist_l.get( &proposal_l, pindex ) && ph2_notify->plist_r.get( &proposal_r, pindex ) ) { proposal_l->life_sec = lsecs; proposal_r->life_sec = lsecs; log.txt( LLOG_DEBUG, "ii : spi_l = 0x%08x\n", ntohl( proposal_l->spi.spi ) ); log.txt( LLOG_DEBUG, "ii : spi_r = 0x%08x\n", ntohl( proposal_r->spi.spi ) ); pindex++; } } if( ldata ) log.txt( LLOG_INFO, "ii : adjusted phase2 sa lifetime to %i kbytes\n", ldata ); if( !lsecs && !ldata ) log.txt( LLOG_INFO, "ii : invalid RESPONDER-LIFETIME attribute data\n" ); ph2_notify->dec( true ); } } } break; } } return LIBIKE_OK; } long _IKED::inform_chk_delete( IDB_PH1 * ph1, IKE_NOTIFY * notify, bool secure ) { assert( ph1 != NULL ); // // build text strings for logging // char txtspi[ LIBIKE_MAX_TEXTSPI ]; char txtaddr_l[ LIBIKE_MAX_TEXTADDR ]; char txtaddr_r[ LIBIKE_MAX_TEXTADDR ]; inform_get_spi( txtspi, ph1, notify ); text_addr( txtaddr_l, &ph1->tunnel->saddr_l, true ); text_addr( txtaddr_r, &ph1->tunnel->saddr_r, true ); // // log the delete notification // log.txt( LLOG_INFO, "ii : received peer DELETE message\n" "ii : - %s -> %s\n" "ii : - %s spi = %s\n", txtaddr_r, txtaddr_l, find_name( NAME_PROTOCOL, notify->proto ), txtspi ); // // only process this message if // it came under the protection // of a mature phase1 sa // if( secure ) if( ( ph1->status() <= XCH_STATUS_MATURE ) || ( ph1->status() >= XCH_STATUS_EXPIRING ) ) return LIBIKE_FAILED; // // process the delete message // switch( notify->spi.size ) { // // phase1 notify // case ( ISAKMP_COOKIE_SIZE * 2 ): { // // attempt to cleanup sa // IDB_PH1 * ph1_delete; if( idb_list_ph1.find( true, &ph1_delete, ph1->tunnel, XCH_STATUS_MATURE, XCH_STATUS_DEAD, ¬ify->spi.cookies ) ) { log.txt( LLOG_INFO, "ii : cleanup, marked phase1 %s for removal\n", txtspi ); ph1_delete->status( XCH_STATUS_DEAD, XCH_FAILED_PEER_DELETE, 0 ); ph1_delete->dec( true ); } break; } // // phase2 notify // case ISAKMP_SPI_SIZE: { // // attempt to cleanup sa // IDB_PH2 * ph2_delete; if( idb_list_ph2.find( true, &ph2_delete, ph1->tunnel, XCH_STATUS_MATURE, XCH_STATUS_DEAD, NULL, NULL, NULL, ¬ify->spi ) ) { log.txt( LLOG_INFO, "DB : cleanup, marked phase2 %s for removal\n", txtspi ); ph2_delete->status( XCH_STATUS_DEAD, XCH_FAILED_PEER_DELETE, 0 ); ph2_delete->dec( true ); } break; } } return LIBIKE_OK; } long _IKED::inform_new_notify( IDB_PH1 * ph1, IDB_PH2 * ph2, unsigned short code, BDATA * data ) { assert( ph1 != NULL ); // // build text strings for logging // char txtaddr_l[ LIBIKE_MAX_TEXTADDR ]; char txtaddr_r[ LIBIKE_MAX_TEXTADDR ]; text_addr( txtaddr_l, &ph1->tunnel->saddr_l, true ); text_addr( txtaddr_r, &ph1->tunnel->saddr_r, true ); // // create message id // IDB_INF inform; inform.new_msgid(); // // will this be a phase1 or phase2 notification // if( ph2 == NULL ) { // // phase1 notification // IKE_NOTIFY notify; notify.type = ISAKMP_PAYLOAD_NOTIFY; notify.code = code; notify.doi = ISAKMP_DOI_IPSEC; notify.proto = ISAKMP_PROTO_ISAKMP; notify.spi.size = sizeof( ph1->cookies ); notify.spi.cookies = ph1->cookies; if( data != NULL ) notify.data.set( *data ); // // log the notification // char txtspi[ LIBIKE_MAX_TEXTSPI ]; inform_get_spi( txtspi, ph1, ¬ify ); log.txt( LLOG_INFO, "ii : sending peer %s notification\n" "ii : - %s -> %s\n" "ii : - %s spi = %s\n" "ii : - data size %i\n", find_name( NAME_NOTIFY, notify.code ), txtaddr_l, txtaddr_r, find_name( NAME_PROTOCOL, notify.proto ), txtspi, notify.data.size() ); // // add notification data // inform.notifications.add( notify ); } else { // // phase2 notification // IKE_NOTIFY notify; notify.type = ISAKMP_PAYLOAD_NOTIFY; notify.code = code; notify.doi = ISAKMP_DOI_IPSEC; notify.proto = ISAKMP_PROTO_ISAKMP; notify.spi.size = 0; if( data != NULL ) notify.data.set( *data ); // // log the notification // log.txt( LLOG_INFO, "ii : sending peer %s notification\n" "ii : - %s -> %s\n", find_name( NAME_NOTIFY, notify.code ), txtaddr_l, txtaddr_r ); // // add notification data // inform.notifications.add( notify ); } return process_inform_send( ph1, &inform ); } long _IKED::inform_new_delete( IDB_PH1 * ph1, IDB_PH2 * ph2 ) { assert( ph1 != NULL ); // // build text strings for logging // char txtaddr_l[ LIBIKE_MAX_TEXTADDR ]; char txtaddr_r[ LIBIKE_MAX_TEXTADDR ]; text_addr( txtaddr_l, &ph1->tunnel->saddr_l, true ); text_addr( txtaddr_r, &ph1->tunnel->saddr_r, true ); // // create message id // IDB_INF inform; inform.new_msgid(); // // will this be a phase1 or phase2 notification // if( ph2 == NULL ) { // // phase1 delete // IKE_NOTIFY notify; notify.type = ISAKMP_PAYLOAD_DELETE; notify.doi = ISAKMP_DOI_IPSEC; notify.proto = ISAKMP_PROTO_ISAKMP; notify.spi.size = sizeof( ph1->cookies ); notify.spi.cookies = ph1->cookies; // // log the delete // char txtspi[ LIBIKE_MAX_TEXTSPI ]; inform_get_spi( txtspi, ph1, ¬ify ); log.txt( LLOG_INFO, "ii : sending peer DELETE message\n" "ii : - %s -> %s\n" "ii : - %s spi = %s\n" "ii : - data size %i\n", txtaddr_l, txtaddr_r, find_name( NAME_PROTOCOL, notify.proto ), txtspi, notify.data.size() ); // // add notification data // inform.notifications.add( notify ); } else { // // phase2 delete // IKE_NOTIFY notify; notify.type = ISAKMP_PAYLOAD_DELETE; notify.doi = ISAKMP_DOI_IPSEC; // // log the delete addresses // log.txt( LLOG_INFO, "ii : sending peer DELETE message\n" "ii : - %s -> %s\n", txtaddr_l, txtaddr_r ); // // add one notify per proposal // IKE_PROPOSAL * proposal; long pindex = 0; while( ph2->plist_l.get( &proposal, pindex++ ) ) { notify.proto = proposal->proto; notify.spi = proposal->spi; // // log the delete protocol and spi // char txtspi[ LIBIKE_MAX_TEXTSPI ]; inform_get_spi( txtspi, ph1, ¬ify ); log.txt( LLOG_INFO, "ii : - %s spi = %s\n" "ii : - data size %i\n", find_name( NAME_PROTOCOL, notify.proto ), txtspi, notify.data.size() ); // // add notification data // inform.notifications.add( notify ); } } return process_inform_send( ph1, &inform ); } ike-2.2.1+dfsg/source/iked/ike.exch.phase1.cpp000066400000000000000000001771401223036517100210130ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "iked.h" long _IKED::process_phase1_recv( IDB_PH1 * ph1, PACKET_IKE & packet, unsigned char payload ) { long result = LIBIKE_OK; // // log packet type // log.txt( LLOG_INFO, "ii : processing phase1 packet ( %i bytes )\n", packet.size() ); // // make sure we are not dealing // with an sa marked for delete // if( ph1->status() == XCH_STATUS_DEAD ) { log.txt( LLOG_ERROR, "!! : phase1 packet ignored ( phase1 marked for death )\n" ); return LIBIKE_OK; } // // make sure we are not dealing // with a mature sa // if( ph1->status() >= XCH_STATUS_MATURE ) { log.txt( LLOG_ERROR, "!! : phase1 packet ignored, resending last packet ( phase1 already mature )\n" ); ph1->resend(); return LIBIKE_OK; } // // attempt to decrypt our packet // if( packet_ike_decrypt( ph1, packet, &ph1->iv ) != LIBIKE_OK ) { log.txt( LLOG_ERROR, "!! : phase1 packet ignored, resending last packet ( packet decryption error )\n" ); ph1->resend(); return LIBIKE_OK; } // // if we are dumping decrypted packets, // we need to rebuild a full packet to // dump to pcap format // if( dump_decrypt ) { // // strip the isakmp encryption flag // packet.buff()[ ISAKMP_FLAGS_OFFSET ] &= ~ISAKMP_FLAG_ENCRYPT; // // build ip dump packet // PACKET_IP packet_ip_dump; packet_ike_encap( packet, packet_ip_dump, ph1->tunnel->saddr_r, ph1->tunnel->saddr_l, ph1->tunnel->natt_version ); // // obtain ethernet header // ETH_HEADER ethhdr; header( packet_ip_dump, ethhdr ); // // dump the packet // pcap_decrypt.dump( ethhdr, packet_ip_dump ); } // // read and process all payloads // uint8_t next_payload; while( payload != ISAKMP_PAYLOAD_NONE ) { // // read the payload header // if( !packet.get_payload( false, next_payload ) ) break; // // call the appropriate payload handler // switch( payload ) { // // security association payload // case ISAKMP_PAYLOAD_SA: if( ph1->xstate & XSTATE_RECV_SA ) log.txt( LLOG_INFO, "<< : ignoring duplicate security association payload\n" ); else { size_t beg = packet.oset(); result = payload_get_sa( packet, ph1->plist_r ); size_t end = packet.oset(); if( !ph1->initiator ) ph1->hda.set( packet.buff() + beg, end - beg ); } ph1->xstate |= XSTATE_RECV_SA; break; // // key exchange payload // case ISAKMP_PAYLOAD_KEX: if( ph1->xstate & XSTATE_RECV_KE ) log.txt( LLOG_INFO, "<< : ignoring duplicate key excahnge payload\n" ); else result = payload_get_kex( packet, ph1->xr ); ph1->xstate |= XSTATE_RECV_KE; break; // // nonce payload // case ISAKMP_PAYLOAD_NONCE: if( ph1->xstate & XSTATE_RECV_NO ) log.txt( LLOG_INFO, "<< : ignoring duplicate nonce payload\n" ); else result = payload_get_nonce( packet, ph1->nonce_r ); ph1->xstate |= XSTATE_RECV_NO; break; // // identity payload // case ISAKMP_PAYLOAD_IDENT: if( ph1->xstate & XSTATE_RECV_ID ) log.txt( LLOG_INFO, "<< : ignoring duplicate id payload\n" ); else { size_t beg = packet.oset(); result = payload_get_ph1id( packet, ph1->ph1id_r ); size_t end = packet.oset(); if( ph1->initiator ) ph1->idr.set( packet.buff() + beg, end - beg ); else ph1->idi.set( packet.buff() + beg, end - beg ); } ph1->xstate |= XSTATE_RECV_ID; break; // // certificate payload // case ISAKMP_PAYLOAD_CERT: { uint8_t type; BDATA cert; result = payload_get_cert( packet, type, cert ); if( result == LIBIKE_OK ) ph1->certs_r.add( type, cert ); ph1->xstate |= XSTATE_RECV_CT; break; } // // certificate request payload // case ISAKMP_PAYLOAD_CERT_REQ: { uint8_t type; BDATA dn; result = payload_get_creq( packet, type, dn ); if( result == LIBIKE_OK ) ph1->creqs_r.add( type, dn ); ph1->xstate |= XSTATE_RECV_CR; break; } // // signature payload // case ISAKMP_PAYLOAD_SIGNATURE: if( ph1->xstate & XSTATE_RECV_SI ) log.txt( LLOG_INFO, "<< : ignoring duplicate signature payload\n" ); else result = payload_get_sign( packet, ph1->sign_r ); ph1->xstate |= XSTATE_RECV_SI; break; // // hash payload // case ISAKMP_PAYLOAD_HASH: if( ph1->xstate & XSTATE_RECV_HA ) log.txt( LLOG_INFO, "<< : ignoring duplicate hash payload\n" ); else result = payload_get_hash( packet, ph1->hash_r, ph1->hash_size ); ph1->xstate |= XSTATE_RECV_HA; break; // // nat discovery payload // case ISAKMP_PAYLOAD_NAT_VXX_DISC: case ISAKMP_PAYLOAD_NAT_RFC_DISC: { BDATA natd; result = payload_get_natd( packet, natd, ph1->hash_size ); if( result == LIBIKE_OK ) ph1->natd_hash_r.add( natd ); ph1->xstate |= XSTATE_RECV_ND; break; } // // vendor id payload // case ISAKMP_PAYLOAD_VEND: { BDATA vend; result = payload_get_vend( packet, vend ); if( result == LIBIKE_OK ) phase1_chk_vend( ph1, vend ); break; } // // notify payload // case ISAKMP_PAYLOAD_NOTIFY: { IKE_NOTIFY notify; result = payload_get_notify( packet, ¬ify ); if( result == LIBIKE_OK ) ph1->notifications.add( notify ); break; } // // unhandled payload // default: log.txt( LLOG_ERROR, "!! : unhandled phase1 payload \'%s\' ( %i )\n", find_name( NAME_PAYLOAD, payload ), payload ); packet.notify = ISAKMP_N_INVALID_PAYLOAD_TYPE; result = LIBIKE_DECODE; break; } // // check that the entire payload was read // if( packet.get_payload_left() ) log.txt( LLOG_ERROR, "!! : unprocessed payload data\n" ); // // now that we have decoded the payload, // perform any required processing here // while( result == LIBIKE_OK ) { // // verify the peers proposal // if( ( ph1->xstate & XSTATE_RECV_SA ) && !( ph1->lstate & LSTATE_CHKPROP ) ) { // // select an acceptable proposal // result = phase1_sel_prop( ph1 ); if( result != LIBIKE_OK ) { packet.notify = ISAKMP_N_NO_PROPOSAL_CHOSEN; break; } // // obtain negotiated authentication type // IKE_PROPOSAL * proposal; ph1->plist_l.get( &proposal, 0 ); ph1->auth_id = proposal->auth_id; if( ( ph1->auth_id == XAUTH_AUTH_INIT_PSK ) || ( ph1->auth_id == XAUTH_AUTH_INIT_RSA ) || ( ph1->auth_id == HYBRID_AUTH_INIT_RSA ) ) ph1->vendopts_l.flag.xauth = true; // // setup the sa dhgroup for main mode // if( ph1->exchange == ISAKMP_EXCH_IDENT_PROTECT ) ph1->setup_dhgrp( proposal ); // // setup the sa transform // ph1->setup_xform( proposal ); ph1->lstate |= LSTATE_CHKPROP; } // // verify the peers identifier // if( ( ph1->xstate & XSTATE_RECV_ID ) && !( ph1->lstate & LSTATE_CHKIDS ) ) { result = phase1_chk_idr( ph1 ); if( result != LIBIKE_OK ) { packet.notify = ISAKMP_N_INVALID_ID_INFORMATION; break; } ph1->lstate |= LSTATE_CHKIDS; } break; } // // check the final paylaod process result // if( result != LIBIKE_OK ) { ph1->status( XCH_STATUS_DEAD, XCH_FAILED_MSG_FORMAT, packet.notify ); return result; } // // read next payload // payload = next_payload; } // // now build and send any response // packets that may be necessary // if( ph1->status() <= XCH_STATUS_DEAD ) process_phase1_send( ph1 ); return LIBIKE_OK; } long _IKED::process_phase1_send( IDB_PH1 * ph1 ) { // // main mode exchange // if( ph1->exchange == ISAKMP_EXCH_IDENT_PROTECT ) { // // isakmp initiator // if( ph1->initiator ) { // // sa + [ + vid's ] packet // if( !( ph1->xstate & XSTATE_SENT_SA ) ) { // // write packet header // PACKET_IKE packet; packet.write( ph1->cookies, ISAKMP_PAYLOAD_SA, ph1->exchange, 0 ); // // add payloads // size_t beg = packet.size() + 4; payload_add_sa( packet, ph1->plist_l, ISAKMP_PAYLOAD_VEND ); size_t end = packet.size(); ph1->hda.set( packet.buff() + beg, end - beg ); phase1_add_vend( ph1, packet, ISAKMP_PAYLOAD_NONE ); packet.done(); // // send packet // packet_ike_send( ph1, ph1, packet, true ); ph1->xstate |= XSTATE_SENT_SA; } // // ke + nonce packet // if( ( ph1->xstate & XSTATE_RECV_SA ) && !( ph1->xstate & XSTATE_SENT_KE ) ) { // // write packet header // PACKET_IKE packet; packet.write( ph1->cookies, ISAKMP_PAYLOAD_KEX, ph1->exchange, 0 ); // // add payloads for authentication type // payload_add_kex( packet, ph1->xl, ISAKMP_PAYLOAD_NONCE ); switch( ph1->auth_id ) { case IKE_AUTH_PRESHARED_KEY: case XAUTH_AUTH_INIT_PSK: { payload_add_nonce( packet, ph1->nonce_l, ph1->natt_pldtype ); break; } case IKE_AUTH_SIG_RSA: case XAUTH_AUTH_INIT_RSA: case HYBRID_AUTH_INIT_RSA: { payload_add_nonce( packet, ph1->nonce_l, ISAKMP_PAYLOAD_CERT_REQ ); payload_add_creq( packet, ISAKMP_CERT_X509_SIG, ph1->natt_pldtype ); ph1->xstate |= XSTATE_SENT_CR; break; } } // // optionally add nat discovery hash payloads // if( ph1->natt_pldtype != ISAKMP_PAYLOAD_NONE ) { phase1_gen_natd( ph1 ); phase1_add_natd( ph1, packet, ISAKMP_PAYLOAD_NONE ); } packet.done(); // // send packet // packet_ike_send( ph1, ph1, packet, true ); ph1->xstate |= XSTATE_SENT_KE; ph1->xstate |= XSTATE_SENT_NO; } // // id + hash || id + [ cert ] + sig + [ cert req ] packet // if( ( ph1->xstate & XSTATE_RECV_KE ) && ( ph1->xstate & XSTATE_RECV_NO ) && !( ph1->xstate & XSTATE_SENT_ID ) ) { // // perform nat traversal check // phase1_chk_natd( ph1 ); // // calculate key material // if( phase1_gen_keys( ph1 ) != LIBIKE_OK ) return LIBIKE_FAILED; // // write packet header // PACKET_IKE packet; packet.write( ph1->cookies, ISAKMP_PAYLOAD_IDENT, ph1->exchange, ISAKMP_FLAG_ENCRYPT ); // // add payloads for authentication type // switch( ph1->auth_id ) { case IKE_AUTH_PRESHARED_KEY: case XAUTH_AUTH_INIT_PSK: case HYBRID_AUTH_INIT_RSA: { size_t pld_beg = packet.size() + 4; payload_add_ph1id( packet, ph1->ph1id_l, ISAKMP_PAYLOAD_HASH ); size_t pld_end = packet.size(); ph1->idi.set( packet.buff() + pld_beg, pld_end - pld_beg ); phase1_gen_hash_i( ph1, ph1->hash_l ); payload_add_hash( packet, ph1->hash_l, ISAKMP_PAYLOAD_NONE ); ph1->xstate |= XSTATE_SENT_HA; break; } case IKE_AUTH_SIG_RSA: case XAUTH_AUTH_INIT_RSA: { size_t pld_beg = packet.size() + 4; payload_add_ph1id( packet, ph1->ph1id_l, ISAKMP_PAYLOAD_CERT ); size_t pld_end = packet.size(); ph1->idi.set( packet.buff() + pld_beg, pld_end - pld_beg ); payload_add_cert( packet, ISAKMP_CERT_X509_SIG, ph1->tunnel->peer->cert_l, ISAKMP_PAYLOAD_SIGNATURE ); BDATA sign; phase1_gen_hash_i( ph1, ph1->hash_l ); prvkey_rsa_encrypt( ph1->tunnel->peer->cert_k, ph1->hash_l, sign ); payload_add_sign( packet, sign, ISAKMP_PAYLOAD_NONE ); ph1->xstate |= XSTATE_SENT_CT; ph1->xstate |= XSTATE_SENT_SI; break; } } packet.done(); // // encrypt and send packet // packet_ike_send( ph1, ph1, packet, false ); ph1->xstate |= XSTATE_SENT_ID; } } // // isakmp responder // if( !ph1->initiator ) { // // sa packet // if( ( ph1->xstate & XSTATE_RECV_SA ) && !( ph1->xstate & XSTATE_SENT_SA ) ) { // // write packet header // PACKET_IKE packet; packet.write( ph1->cookies, ISAKMP_PAYLOAD_SA, ph1->exchange, 0 ); // // add payloads // payload_add_sa( packet, ph1->plist_l, ISAKMP_PAYLOAD_VEND ); phase1_add_vend( ph1, packet, ISAKMP_PAYLOAD_NONE ); packet.done(); // // send packet // packet_ike_send( ph1, ph1, packet, true ); ph1->xstate |= XSTATE_SENT_SA; } // // ke + nonce packet // if( ( ph1->xstate & XSTATE_RECV_KE ) && ( ph1->xstate & XSTATE_RECV_NO ) && !( ph1->xstate & XSTATE_SENT_KE ) ) { // // write the packet header // PACKET_IKE packet; packet.write( ph1->cookies, ISAKMP_PAYLOAD_KEX, ph1->exchange, 0 ); // // add payloads for authentication type // payload_add_kex( packet, ph1->xl, ISAKMP_PAYLOAD_NONCE ); switch( ph1->auth_id ) { case IKE_AUTH_PRESHARED_KEY: case XAUTH_AUTH_INIT_PSK: { payload_add_nonce( packet, ph1->nonce_l, ph1->natt_pldtype ); break; } case IKE_AUTH_SIG_RSA: case XAUTH_AUTH_INIT_RSA: case HYBRID_AUTH_INIT_RSA: { payload_add_nonce( packet, ph1->nonce_l, ISAKMP_PAYLOAD_CERT_REQ ); payload_add_creq( packet, ISAKMP_CERT_X509_SIG, ph1->natt_pldtype ); ph1->xstate |= XSTATE_SENT_CR; break; } } // // optionally add nat discovery hash payloads // if( ph1->natt_pldtype != ISAKMP_PAYLOAD_NONE ) { phase1_gen_natd( ph1 ); phase1_add_natd( ph1, packet, ISAKMP_PAYLOAD_NONE ); } packet.done(); // // send packet // packet_ike_send( ph1, ph1, packet, true ); ph1->xstate |= XSTATE_SENT_KE; ph1->xstate |= XSTATE_SENT_NO; // // calculate key material // if( phase1_gen_keys( ph1 ) != LIBIKE_OK ) return LIBIKE_FAILED; } // // id + hash || id + [ cert ] + sign packet // if( ( ph1->xstate & XSTATE_RECV_ID ) && !( ph1->xstate & XSTATE_SENT_ID ) ) { // // perform nat traversal check // phase1_chk_natd( ph1 ); // // build packet for authentication type // switch( ph1->auth_id ) { case IKE_AUTH_PRESHARED_KEY: case XAUTH_AUTH_INIT_PSK: { if( !( ph1->xstate & XSTATE_RECV_HA ) ) break; // // write packet header // PACKET_IKE packet; packet.write( ph1->cookies, ISAKMP_PAYLOAD_IDENT, ph1->exchange, ISAKMP_FLAG_ENCRYPT ); // // add payloads // size_t pld_beg = packet.size() + 4; payload_add_ph1id( packet, ph1->ph1id_l, ISAKMP_PAYLOAD_HASH ); size_t pld_end = packet.size(); ph1->idr.set( packet.buff() + pld_beg, pld_end - pld_beg ); phase1_gen_hash_r( ph1, ph1->hash_l ); payload_add_hash( packet, ph1->hash_l, ISAKMP_PAYLOAD_NONE ); packet.done(); // // send packet // packet_ike_send( ph1, ph1, packet, false ); ph1->xstate |= XSTATE_SENT_ID; ph1->xstate |= XSTATE_SENT_HA; break; } case IKE_AUTH_SIG_RSA: case XAUTH_AUTH_INIT_RSA: case HYBRID_AUTH_INIT_RSA: { if( ph1->auth_id == XAUTH_AUTH_INIT_RSA ) { // // mutual rsa modes we should see a signature // if( !( ph1->xstate & XSTATE_RECV_SI ) ) break; } else { // // hybrid rsa modes we should see a hash // if( !( ph1->xstate & XSTATE_RECV_HA ) ) break; } // // write packet header // PACKET_IKE packet; packet.write( ph1->cookies, ISAKMP_PAYLOAD_IDENT, ph1->exchange, ISAKMP_FLAG_ENCRYPT ); // // add payloads // size_t pld_beg = packet.size() + 4; payload_add_ph1id( packet, ph1->ph1id_l, ISAKMP_PAYLOAD_CERT ); size_t pld_end = packet.size(); ph1->idr.set( packet.buff() + pld_beg, pld_end - pld_beg ); payload_add_cert( packet, ISAKMP_CERT_X509_SIG, ph1->tunnel->peer->cert_l, ISAKMP_PAYLOAD_SIGNATURE ); BDATA sign; phase1_gen_hash_r( ph1, ph1->hash_l ); prvkey_rsa_encrypt( ph1->tunnel->peer->cert_k, ph1->hash_l, sign ); payload_add_sign( packet, sign, ISAKMP_PAYLOAD_NONE ); // // send packet // packet_ike_send( ph1, ph1, packet, false ); ph1->xstate |= XSTATE_SENT_ID; ph1->xstate |= XSTATE_SENT_CT; ph1->xstate |= XSTATE_SENT_SI; break; } } } } } // // aggressive mode exchange // if( ph1->exchange == ISAKMP_EXCH_AGGRESSIVE ) { // // isakmp initiator // if( ph1->initiator ) { // // sa + ke + no + id [ + vid's ] packet // if( !( ph1->xstate & XSTATE_SENT_SA ) ) { // // write packet header // PACKET_IKE packet; packet.write( ph1->cookies, ISAKMP_PAYLOAD_SA, ph1->exchange, 0 ); // // add payloads for authentication type // size_t beg = packet.size() + 4; payload_add_sa( packet, ph1->plist_l, ISAKMP_PAYLOAD_KEX ); size_t end = packet.size(); ph1->hda.set( packet.buff() + beg, end - beg ); payload_add_kex( packet, ph1->xl, ISAKMP_PAYLOAD_NONCE ); switch( ph1->auth_id ) { case IKE_AUTH_PRESHARED_KEY: case XAUTH_AUTH_INIT_PSK: { payload_add_nonce( packet, ph1->nonce_l, ISAKMP_PAYLOAD_IDENT ); break; } case IKE_AUTH_SIG_RSA: case XAUTH_AUTH_INIT_RSA: case HYBRID_AUTH_INIT_RSA: { payload_add_nonce( packet, ph1->nonce_l, ISAKMP_PAYLOAD_CERT_REQ ); payload_add_creq( packet, ISAKMP_CERT_X509_SIG, ISAKMP_PAYLOAD_IDENT ); ph1->xstate |= XSTATE_SENT_CR; break; } } beg = packet.size() + 4; payload_add_ph1id( packet, ph1->ph1id_l, ISAKMP_PAYLOAD_VEND ); end = packet.size(); ph1->idi.set( packet.buff() + beg, end - beg ); phase1_add_vend( ph1, packet, ISAKMP_PAYLOAD_NONE ); packet.done(); // // send packet // packet_ike_send( ph1, ph1, packet, true ); ph1->xstate |= XSTATE_SENT_SA; ph1->xstate |= XSTATE_SENT_KE; ph1->xstate |= XSTATE_SENT_NO; ph1->xstate |= XSTATE_SENT_ID; } // // hash || [ cert + ] sig [ + natd + natd ] packet // if( ( ph1->xstate & XSTATE_RECV_KE ) && ( ph1->xstate & XSTATE_RECV_NO ) && ( ph1->xstate & XSTATE_RECV_ID ) ) { // // perform nat traversal check // phase1_chk_natd( ph1 ); // // build packet for authentication type // switch( ph1->auth_id ) { case IKE_AUTH_PRESHARED_KEY: case XAUTH_AUTH_INIT_PSK: case HYBRID_AUTH_INIT_RSA: { if( ( ( ( ph1->auth_id == IKE_AUTH_PRESHARED_KEY ) || ( ph1->auth_id == XAUTH_AUTH_INIT_PSK ) ) && ( ph1->xstate & XSTATE_RECV_HA ) && !( ph1->xstate & XSTATE_SENT_HA ) ) || ( ( ph1->auth_id == HYBRID_AUTH_INIT_RSA ) && ( ph1->xstate & XSTATE_RECV_SI ) && !( ph1->xstate & XSTATE_SENT_HA ) ) ) { // // calculate key material // if( phase1_gen_keys( ph1 ) != LIBIKE_OK ) break; // // write packet header // PACKET_IKE packet; packet.write( ph1->cookies, ISAKMP_PAYLOAD_HASH, ph1->exchange, ISAKMP_FLAG_ENCRYPT ); // // cisco hybrid authentication uses an extra // notification payload containing the group // password hash // uint8_t nextp = ph1->natt_pldtype; if( ph1->tunnel->xconf.opts & IPSEC_OPTS_CISCO_GRP ) nextp = ISAKMP_PAYLOAD_NOTIFY; // // add payloads // phase1_gen_hash_i( ph1, ph1->hash_l ); payload_add_hash( packet, ph1->hash_l, nextp ); // // optionally add unity notification payload // if( ph1->tunnel->xconf.opts & IPSEC_OPTS_CISCO_GRP ) { // // generate the group password hash // BDATA psk_hash; psk_hash.size( ph1->hash_size ); HMAC_CTX ctx_prf; HMAC_CTX_init( &ctx_prf ); HMAC_Init_ex( &ctx_prf, ph1->skeyid.buff(), ( int ) ph1->skeyid.size(), ph1->evp_hash, NULL ); HMAC_Update( &ctx_prf, ph1->tunnel->peer->psk.buff(), ph1->tunnel->peer->psk.size() ); HMAC_Final( &ctx_prf, psk_hash.buff(), NULL ); HMAC_CTX_cleanup( &ctx_prf ); // // add the notification payload // IKE_NOTIFY notify; notify.type = ISAKMP_PAYLOAD_NOTIFY; notify.code = ISAKMP_N_UNITY_GROUP_HASH; notify.doi = ISAKMP_DOI_IPSEC; notify.proto = ISAKMP_PROTO_ISAKMP; notify.spi.size = sizeof( ph1->cookies ); notify.spi.cookies = ph1->cookies; notify.data.set( psk_hash ); payload_add_notify( packet, ¬ify, ph1->natt_pldtype ); } // // optionally add nat discovery hash payloads // if( ph1->natt_pldtype != ISAKMP_PAYLOAD_NONE ) { phase1_gen_natd( ph1 ); phase1_add_natd( ph1, packet, ISAKMP_PAYLOAD_NONE ); } packet.done(); // // send packet // packet_ike_send( ph1, ph1, packet, false ); ph1->xstate |= XSTATE_SENT_HA; } break; } case IKE_AUTH_SIG_RSA: case XAUTH_AUTH_INIT_RSA: { if( ( ph1->xstate & XSTATE_RECV_SI ) && !( ph1->xstate & XSTATE_SENT_SI ) ) { // // calculate key material // if( phase1_gen_keys( ph1 ) != LIBIKE_OK ) break; // // write packet header // PACKET_IKE packet; packet.write( ph1->cookies, ISAKMP_PAYLOAD_CERT, ph1->exchange, ISAKMP_FLAG_ENCRYPT ); // // add payloads // payload_add_cert( packet, ISAKMP_CERT_X509_SIG, ph1->tunnel->peer->cert_l, ISAKMP_PAYLOAD_SIGNATURE ); BDATA sign; phase1_gen_hash_i( ph1, ph1->hash_l ); prvkey_rsa_encrypt( ph1->tunnel->peer->cert_k, ph1->hash_l, sign ); payload_add_sign( packet, sign, ph1->natt_pldtype ); // // optionally add nat discovery hash payloads // if( ph1->natt_pldtype != ISAKMP_PAYLOAD_NONE ) { phase1_gen_natd( ph1 ); phase1_add_natd( ph1, packet, ISAKMP_PAYLOAD_NONE ); } packet.done(); // // send packet // packet_ike_send( ph1, ph1, packet, false ); ph1->xstate |= XSTATE_SENT_CT; ph1->xstate |= XSTATE_SENT_SI; } break; } } } } // // isakmp responder // if( !ph1->initiator ) { // // sa + ke + no + hash || [ cert + ] sig [ + natd + natd ] [ + vid's ] packet // if( ( ph1->xstate & XSTATE_RECV_SA ) && ( ph1->xstate & XSTATE_RECV_KE ) && ( ph1->xstate & XSTATE_RECV_NO ) && ( ph1->xstate & XSTATE_RECV_ID ) && !( ph1->xstate & XSTATE_SENT_SA ) ) { // // calculate key material // if( phase1_gen_keys( ph1 ) != LIBIKE_OK ) return LIBIKE_FAILED; // // write packet header // PACKET_IKE packet; packet.write( ph1->cookies, ISAKMP_PAYLOAD_SA, ph1->exchange, 0 ); // // add payloads // payload_add_sa( packet, ph1->plist_l, ISAKMP_PAYLOAD_KEX ); payload_add_kex( packet, ph1->xl, ISAKMP_PAYLOAD_NONCE ); payload_add_nonce( packet, ph1->nonce_l, ISAKMP_PAYLOAD_IDENT ); // // add payloads for authentication type // switch( ph1->auth_id ) { case IKE_AUTH_PRESHARED_KEY: case XAUTH_AUTH_INIT_PSK: case HYBRID_AUTH_INIT_RSA: { size_t pld_beg = packet.size() + 4; payload_add_ph1id( packet, ph1->ph1id_l, ISAKMP_PAYLOAD_HASH ); size_t pld_end = packet.size(); ph1->idr.set( packet.buff() + pld_beg, pld_end - pld_beg ); phase1_gen_hash_r( ph1, ph1->hash_l ); payload_add_hash( packet, ph1->hash_l, ISAKMP_PAYLOAD_VEND ); ph1->xstate |= XSTATE_SENT_HA; break; } case IKE_AUTH_SIG_RSA: case XAUTH_AUTH_INIT_RSA: { size_t pld_beg = packet.size() + 4; payload_add_ph1id( packet, ph1->ph1id_l, ISAKMP_PAYLOAD_CERT ); size_t pld_end = packet.size(); ph1->idr.set( packet.buff() + pld_beg, pld_end - pld_beg ); payload_add_cert( packet, ISAKMP_CERT_X509_SIG, ph1->tunnel->peer->cert_l, ISAKMP_PAYLOAD_CERT_REQ ); payload_add_creq( packet, ISAKMP_CERT_X509_SIG, ISAKMP_PAYLOAD_SIGNATURE ); BDATA sign; phase1_gen_hash_r( ph1, ph1->hash_l ); prvkey_rsa_encrypt( ph1->tunnel->peer->cert_k, ph1->hash_l, sign ); payload_add_sign( packet, sign, ISAKMP_PAYLOAD_VEND ); ph1->xstate |= XSTATE_SENT_CT; ph1->xstate |= XSTATE_SENT_CR; ph1->xstate |= XSTATE_SENT_SI; break; } } phase1_add_vend( ph1, packet, ph1->natt_pldtype ); // // optionally add nat discovery hash payloads // if( ph1->natt_pldtype != ISAKMP_PAYLOAD_NONE ) { phase1_gen_natd( ph1 ); phase1_add_natd( ph1, packet, ISAKMP_PAYLOAD_NONE ); } // // send packet // packet.done(); packet_ike_send( ph1, ph1, packet, false ); ph1->xstate |= XSTATE_SENT_SA; ph1->xstate |= XSTATE_SENT_KE; ph1->xstate |= XSTATE_SENT_NO; ph1->xstate |= XSTATE_SENT_ID; } // // post negotiation processing // if( ( ph1->xstate & XSTATE_RECV_HA ) || ( ph1->xstate & XSTATE_RECV_CT ) ) { // // check and enable natt if required // phase1_chk_natd( ph1 ); } } } // // is it time to verify our // peers hash or signature // if( ( ph1->status() < XCH_STATUS_MATURE ) && ( ph1->lstate & LSTATE_HASKEYS ) && ( ph1->xstate & XSTATE_RECV_ID ) ) { // // check the peers hash value // if( ( ph1->auth_id == IKE_AUTH_PRESHARED_KEY ) || ( ph1->auth_id == XAUTH_AUTH_INIT_PSK ) || ( ph1->auth_id == HYBRID_AUTH_INIT_RSA && !ph1->initiator ) ) { if( ph1->xstate & XSTATE_RECV_HA ) { if( phase1_chk_hash( ph1 ) == LIBIKE_OK ) ph1->status( XCH_STATUS_MATURE, XCH_NORMAL, 0 ); else ph1->status( XCH_STATUS_DEAD, XCH_FAILED_PEER_AUTH, ISAKMP_N_AUTHENTICATION_FAILED ); ph1->clean(); } } // // check the peers signature value // if( ( ph1->auth_id == IKE_AUTH_SIG_RSA ) || ( ph1->auth_id == XAUTH_AUTH_INIT_RSA ) || ( ph1->auth_id == HYBRID_AUTH_INIT_RSA && ph1->initiator ) ) { if( ph1->xstate & XSTATE_RECV_SI ) { if( phase1_chk_sign( ph1 ) == LIBIKE_OK ) ph1->status( XCH_STATUS_MATURE, XCH_NORMAL, 0 ); else ph1->status( XCH_STATUS_DEAD, XCH_FAILED_PEER_AUTH, ISAKMP_N_AUTHENTICATION_FAILED ); ph1->clean(); } } } // // if this tunnel has just now // completed initialization, we // may need to do a few things // if( ph1->status() == XCH_STATUS_MATURE ) { // // special handling for tunnel initialization // if( !( ph1->tunnel->tstate & TSTATE_INITIALIZED ) ) { // // send our inital contact notification // inform_new_notify( ph1, NULL, ISAKMP_N_INITIAL_CONTACT ); // // add tunnel natt event // if( ph1->tunnel->natt_version != IPSEC_NATT_NONE ) { ph1->tunnel->inc( true ); ph1->tunnel->event_natt.delay = ph1->tunnel->peer->natt_rate * 1000; ith_timer.add( &ph1->tunnel->event_natt ); } // // add tunnel dpd event // if( ( ph1->tunnel->peer->dpd_mode == IPSEC_DPD_FORCE ) || ( ph1->vendopts_l.flag.dpdv1 && ph1->vendopts_r.flag.dpdv1 ) ) { ph1->tunnel->stats.dpd = true; ph1->tunnel->inc( true ); ph1->tunnel->event_dpd.delay = ph1->tunnel->peer->dpd_delay * 1000; ith_timer.add( &ph1->tunnel->event_dpd ); } // // flag ph1->tunnel as initialized // ph1->tunnel->tstate |= TSTATE_INITIALIZED; } // // determine the policy level if auto // if( ph1->tunnel->peer->plcy_level == POLICY_LEVEL_AUTO ) { // // unity compatible default to shared level // and all others defult to unique // if( ph1->vendopts_r.flag.unity && !ph1->vendopts_r.flag.kame ) ph1->tunnel->peer->plcy_level = POLICY_LEVEL_SHARED; else ph1->tunnel->peer->plcy_level = POLICY_LEVEL_UNIQUE; } // // if we are to generate a policy // list before config, do this now // if( !ph1->initiator ) if( ph1->tunnel->peer->plcy_mode == POLICY_MODE_COMPAT ) policy_list_create( ph1->tunnel, ph1->initiator ); // // determine if client configurtaion // processing should be initiated // switch( ph1->tunnel->peer->contact ) { case IPSEC_CONTACT_RESP: case IPSEC_CONTACT_BOTH: { // // inititate xauth operation if required // if( !ph1->initiator && ph1->vendopts_l.flag.xauth ) { IDB_CFG * cfg = new IDB_CFG( ph1, true ); cfg->add( true ); process_config_send( ph1, cfg ); cfg->dec( true ); } break; } case IPSEC_CONTACT_CLIENT: { // // peer will initiate xauth if required // if( ph1->initiator && !ph1->vendopts_l.flag.xauth ) { // // initiate the client configuration // processing unless in push mode // if( ph1->tunnel->peer->xconf_mode != CONFIG_MODE_PUSH ) { IDB_CFG * cfg = new IDB_CFG( ph1, true ); cfg->add( true ); process_config_send( ph1, cfg ); cfg->dec( true ); } } break; } } // // obtain our negotiated proposal // IKE_PROPOSAL * proposal; ph1->plist_l.get( &proposal, 0 ); // // add pahse1 soft expire event // ph1->inc( true ); ph1->event_soft.delay = proposal->life_sec; ph1->event_soft.delay *= PFKEY_SOFT_LIFETIME_RATE; ph1->event_soft.delay /= 100; ph1->event_soft.delay *= 1000; ith_timer.add( &ph1->event_soft ); // // add pahse1 hard expire event // ph1->inc( true ); ph1->event_hard.delay = proposal->life_sec; ph1->event_hard.delay *= 1000; ith_timer.add( &ph1->event_hard ); // // add pahse1 dead event // ph1->inc( true ); ph1->event_dead.delay = proposal->life_sec + 6; ph1->event_dead.delay *= 1000; ith_timer.add( &ph1->event_dead ); // // enable fragmentation support // if( ph1->vendopts_l.flag.frag && ph1->vendopts_r.flag.frag ) ph1->tunnel->stats.frag = true; // // locate any pending phase2 // handles for this tunnel and // begin negotiataions // IDB_PH2 * ph2; while( idb_list_ph2.find( true, &ph2, ph1->tunnel, XCH_STATUS_PENDING, XCH_STATUS_PENDING, NULL, NULL, NULL, NULL ) ) { // // begin negotiations // process_phase2_send( ph1, ph2 ); // // remove pending flag // ph2->status( XCH_STATUS_LARVAL, XCH_NORMAL, 0 ); ph2->dec( true ); } } return LIBIKE_OK; } long _IKED::phase1_gen_keys( IDB_PH1 * ph1 ) { // // obtain our negotiated proposal // IKE_PROPOSAL * proposal; ph1->plist_l.get( &proposal, 0 ); // // determine shared secret // if( level >= LLOG_DECODE ) { BDATA prv; prv.size( ph1->dh_size ); BN_bn2bin( ph1->dh->priv_key, prv.buff() ); log.bin( LLOG_DECODE, LLOG_DECODE, prv.buff(), prv.size(), "ii : computed DH private key" ); log.bin( LLOG_DECODE, LLOG_DECODE, ph1->xl.buff(), ph1->xl.size(), "ii : computed DH public key" ); log.bin( LLOG_DECODE, LLOG_DECODE, ph1->xr.buff(), ph1->xr.size(), "ii : received DH public key" ); } // // validate the dh group size // if( ph1->xr.size() != ph1->dh_size ) { log.txt( LLOG_ERROR, "!! : DH group size mismatch ( %d != %d )\n", ph1->xr.size(), ph1->dh_size ); ph1->status( XCH_STATUS_DEAD, XCH_FAILED_MSG_FORMAT, 0 ); return LIBIKE_FAILED; } // // determine shared secret // BIGNUM * gx = BN_new(); BN_bin2bn( ph1->xr.buff(), ph1->dh_size, gx ); BDATA shared; shared.set( 0, ph1->dh_size ); long result = DH_compute_key( shared.buff(), gx, ph1->dh ); BN_free( gx ); if( result < 0 ) { log.txt( LLOG_ERROR, "!! : failed to compute DH shared secret\n" ); ph1->status( XCH_STATUS_DEAD, XCH_FAILED_MSG_CRYPTO, 0 ); return LIBIKE_FAILED; } // // fixup shared secret buffer alignment // if( ph1->dh_size > result ) { log.txt( LLOG_DEBUG, "ww : short DH shared secret computed\n" ); shared.size( result ); shared.ins( 0, ph1->dh_size - result ); } log.bin( LLOG_DEBUG, LLOG_DECODE, shared.buff(), shared.size(), "== : DH shared secret" ); // // compute SKEYID // unsigned char skeyid_data[ HMAC_MAX_MD_CBLOCK ]; long skeyid_size = EVP_MD_size( ph1->evp_hash ); switch( proposal->auth_id ) { // // preshared key // // SKEYID = prf( pre-shared-key, Ni_b | Nr_b ) // case IKE_AUTH_PRESHARED_KEY: case XAUTH_AUTH_INIT_PSK: case XAUTH_AUTH_RESP_PSK: { HMAC_CTX ctx_prf; HMAC_CTX_init( &ctx_prf ); HMAC_Init_ex( &ctx_prf, ph1->tunnel->peer->psk.buff(), ( int ) ph1->tunnel->peer->psk.size(), ph1->evp_hash, NULL ); if( ph1->initiator ) { HMAC_Update( &ctx_prf, ph1->nonce_l.buff(), ph1->nonce_l.size() ); HMAC_Update( &ctx_prf, ph1->nonce_r.buff(), ph1->nonce_r.size() ); } else { HMAC_Update( &ctx_prf, ph1->nonce_r.buff(), ph1->nonce_r.size() ); HMAC_Update( &ctx_prf, ph1->nonce_l.buff(), ph1->nonce_l.size() ); } HMAC_Final( &ctx_prf, skeyid_data, NULL ); HMAC_CTX_cleanup( &ctx_prf ); break; } // // digital signature // // SKEYID = prf( Ni_b | Nr_b, g^xy ) // case IKE_AUTH_SIG_RSA: case HYBRID_AUTH_INIT_RSA: case HYBRID_AUTH_RESP_RSA: case XAUTH_AUTH_INIT_RSA: case XAUTH_AUTH_RESP_RSA: { BDATA nonce; if( ph1->initiator ) { nonce.add( ph1->nonce_l ); nonce.add( ph1->nonce_r ); } else { nonce.add( ph1->nonce_r ); nonce.add( ph1->nonce_l ); } HMAC_CTX ctx_prf; HMAC_CTX_init( &ctx_prf ); HMAC_Init_ex( &ctx_prf, nonce.buff(), ( int ) nonce.size(), ph1->evp_hash, NULL ); HMAC_Update( &ctx_prf, shared.buff(), shared.size() ); HMAC_Final( &ctx_prf, skeyid_data, NULL ); HMAC_CTX_cleanup( &ctx_prf ); break; } } ph1->skeyid.set( skeyid_data, skeyid_size ); log.bin( LLOG_DEBUG, LLOG_DECODE, skeyid_data, skeyid_size, "== : SETKEYID" ); // // compute SKEYID_d // HMAC_CTX ctx_prf; HMAC_CTX_init( &ctx_prf ); HMAC_Init_ex( &ctx_prf, ph1->skeyid.buff(), ( int ) ph1->skeyid.size(), ph1->evp_hash, NULL ); HMAC_Update( &ctx_prf, shared.buff(), shared.size() ); HMAC_Update( &ctx_prf, ph1->cookies.i, ISAKMP_COOKIE_SIZE ); HMAC_Update( &ctx_prf, ph1->cookies.r, ISAKMP_COOKIE_SIZE ); HMAC_Update( &ctx_prf, ( unsigned char * ) "\0", 1 ); HMAC_Final( &ctx_prf, skeyid_data, NULL ); ph1->skeyid_d.set( skeyid_data, skeyid_size ); log.bin( LLOG_DEBUG, LLOG_DECODE, skeyid_data, skeyid_size, "== : SETKEYID_d" ); // // compute SKEYID_a // HMAC_Init_ex( &ctx_prf, ph1->skeyid.buff(), ( int ) ph1->skeyid.size(), ph1->evp_hash, NULL ); HMAC_Update( &ctx_prf, skeyid_data, skeyid_size ); HMAC_Update( &ctx_prf, shared.buff(), shared.size() ); HMAC_Update( &ctx_prf, ph1->cookies.i, ISAKMP_COOKIE_SIZE ); HMAC_Update( &ctx_prf, ph1->cookies.r, ISAKMP_COOKIE_SIZE ); HMAC_Update( &ctx_prf, ( unsigned char * ) "\1", 1 ); HMAC_Final( &ctx_prf, skeyid_data, NULL ); ph1->skeyid_a.set( skeyid_data, skeyid_size ); log.bin( LLOG_DEBUG, LLOG_DECODE, skeyid_data, skeyid_size, "== : SETKEYID_a" ); // // compute SKEYID_e // HMAC_Init_ex( &ctx_prf, ph1->skeyid.buff(), ( int ) ph1->skeyid.size(), ph1->evp_hash, NULL ); HMAC_Update( &ctx_prf, skeyid_data, skeyid_size ); HMAC_Update( &ctx_prf, shared.buff(), shared.size() ); HMAC_Update( &ctx_prf, ph1->cookies.i, ISAKMP_COOKIE_SIZE ); HMAC_Update( &ctx_prf, ph1->cookies.r, ISAKMP_COOKIE_SIZE ); HMAC_Update( &ctx_prf, ( unsigned char * ) "\2", 1 ); HMAC_Final( &ctx_prf, skeyid_data, NULL ); ph1->skeyid_e.set( skeyid_data, skeyid_size ); log.bin( LLOG_DEBUG, LLOG_DECODE, skeyid_data, skeyid_size, "== : SETKEYID_e" ); // // clobber dh shared secret // shared.del( true ); // compute cipher key data unsigned char key_data[ EVP_MAX_KEY_LENGTH + HMAC_MAX_MD_CBLOCK ]; long key_size = EVP_CIPHER_key_length( ph1->evp_cipher ); if( proposal->ciph_kl ) key_size = ( proposal->ciph_kl + 7 ) / 8; // // if the cipher requires more key material // than SKEYID_e provides, extend it using // a recursive algorithm // if( skeyid_size < key_size ) { // grow our key to be a multiple // of SKEYID_e ( HMAC block size ) if( key_size % skeyid_size ) key_size += skeyid_size - ( key_size % skeyid_size ); // create extended key data HMAC_Init_ex( &ctx_prf, skeyid_data, skeyid_size, ph1->evp_hash, NULL ); HMAC_Update( &ctx_prf, ( unsigned char * ) "\0", 1 ); HMAC_Final( &ctx_prf, key_data, NULL ); for( long size = skeyid_size; size < key_size; size += skeyid_size ) { HMAC_Init_ex( &ctx_prf, skeyid_data, skeyid_size, ph1->evp_hash, NULL ); HMAC_Update( &ctx_prf, key_data + size - skeyid_size, skeyid_size ); HMAC_Final( &ctx_prf, key_data + size, NULL ); } } else { // copy the key data memcpy( key_data, skeyid_data, key_size ); } HMAC_CTX_cleanup( &ctx_prf ); if( proposal->ciph_kl ) key_size = ( proposal->ciph_kl + 7 ) / 8; ph1->key.set( key_data, key_size ); log.bin( LLOG_DEBUG, LLOG_DECODE, key_data, key_size, "== : cipher key" ); // // compute cipher iv data // unsigned char iv_data[ HMAC_MAX_MD_CBLOCK ]; unsigned long iv_size = EVP_CIPHER_iv_length( ph1->evp_cipher ); EVP_MD_CTX ctx_hash; EVP_DigestInit( &ctx_hash, ph1->evp_hash ); if( ph1->initiator ) { EVP_DigestUpdate( &ctx_hash, ph1->xl.buff(), ph1->xl.size() ); EVP_DigestUpdate( &ctx_hash, ph1->xr.buff(), ph1->xr.size() ); } else { EVP_DigestUpdate( &ctx_hash, ph1->xr.buff(), ph1->xr.size() ); EVP_DigestUpdate( &ctx_hash, ph1->xl.buff(), ph1->xl.size() ); } EVP_DigestFinal( &ctx_hash, iv_data, NULL ); EVP_MD_CTX_cleanup( &ctx_hash ); ph1->iv.set( iv_data, iv_size ); log.bin( LLOG_DEBUG, LLOG_DECODE, iv_data, iv_size, "== : cipher iv" ); // // flag key material calculated // ph1->lstate |= LSTATE_HASKEYS; return LIBIKE_OK; } long _IKED::phase1_gen_hash_i( IDB_PH1 * sa, BDATA & hash ) { // // compute the initiators hash // hash.size( sa->hash_size ); HMAC_CTX ctx_prf; HMAC_CTX_init( &ctx_prf ); HMAC_Init_ex( &ctx_prf, sa->skeyid.buff(), ( int ) sa->skeyid.size(), sa->evp_hash, NULL ); if( sa->initiator ) { HMAC_Update( &ctx_prf, sa->xl.buff(), sa->xl.size() ); HMAC_Update( &ctx_prf, sa->xr.buff(), sa->xr.size() ); } else { HMAC_Update( &ctx_prf, sa->xr.buff(), sa->xr.size() ); HMAC_Update( &ctx_prf, sa->xl.buff(), sa->xl.size() ); } HMAC_Update( &ctx_prf, sa->cookies.i, ISAKMP_COOKIE_SIZE ); HMAC_Update( &ctx_prf, sa->cookies.r, ISAKMP_COOKIE_SIZE ); HMAC_Update( &ctx_prf, sa->hda.buff(), sa->hda.size() ); HMAC_Update( &ctx_prf, sa->idi.buff(), sa->idi.size() ); HMAC_Final( &ctx_prf, hash.buff(), NULL ); HMAC_CTX_cleanup( &ctx_prf ); log.bin( LLOG_DEBUG, LLOG_DECODE, hash.buff(), hash.size(), "== : phase1 hash_i ( computed )" ); return LIBIKE_OK; } long _IKED::phase1_gen_hash_r( IDB_PH1 * sa, BDATA & hash ) { // // compute the responders hash // hash.size( sa->hash_size ); HMAC_CTX ctx_prf; HMAC_CTX_init( &ctx_prf ); HMAC_Init_ex( &ctx_prf, sa->skeyid.buff(), ( int ) sa->skeyid.size(), sa->evp_hash, NULL ); if( sa->initiator ) { HMAC_Update( &ctx_prf, sa->xr.buff(), sa->xr.size() ); HMAC_Update( &ctx_prf, sa->xl.buff(), sa->xl.size() ); } else { HMAC_Update( &ctx_prf, sa->xl.buff(), sa->xl.size() ); HMAC_Update( &ctx_prf, sa->xr.buff(), sa->xr.size() ); } HMAC_Update( &ctx_prf, sa->cookies.r, ISAKMP_COOKIE_SIZE ); HMAC_Update( &ctx_prf, sa->cookies.i, ISAKMP_COOKIE_SIZE ); HMAC_Update( &ctx_prf, sa->hda.buff(), sa->hda.size() ); HMAC_Update( &ctx_prf, sa->idr.buff(), sa->idr.size() ); HMAC_Final( &ctx_prf, hash.buff(), NULL ); HMAC_CTX_cleanup( &ctx_prf ); log.bin( LLOG_DEBUG, LLOG_DECODE, hash.buff(), hash.size(), "== : phase1 hash_r ( computed )" ); return LIBIKE_OK; } inline uint8_t vendpld( long & count, uint8_t next ) { if( --count ) return ISAKMP_PAYLOAD_VEND; else return next; } long _IKED::phase1_add_vend( IDB_PH1 * ph1, PACKET_IKE & packet, uint8_t next ) { // // determine vendor id count // long vid_count = 0; if( ph1->vendopts_l.flag.xauth ) vid_count++; if( ph1->vendopts_l.flag.natt ) { if( ph1->tunnel->peer->natt_mode == IPSEC_NATT_ENABLE ) vid_count += 5; if( ph1->tunnel->peer->natt_mode == IPSEC_NATT_FORCE_DRAFT ) vid_count += 2; if( ph1->tunnel->peer->natt_mode == IPSEC_NATT_FORCE_RFC ) vid_count += 3; } if( ph1->vendopts_l.flag.frag ) vid_count++; if( ph1->vendopts_l.flag.dpdv1 ) vid_count += 2; if( ph1->vendopts_l.flag.ssoft ) vid_count++; if( ph1->vendopts_l.flag.netsc ) vid_count++; if( ph1->vendopts_l.flag.swind ) vid_count++; if( ph1->vendopts_l.flag.unity ) vid_count++; if( ph1->vendopts_l.flag.chkpt ) vid_count++; // // optionally add xauth vendor id payload // if( ph1->vendopts_l.flag.xauth ) { payload_add_vend( packet, vend_xauth, vendpld( vid_count, next ) ); log.txt( LLOG_INFO, "ii : local supports XAUTH\n" ); } // // optionally add natt vendor id payloads // if( ph1->vendopts_l.flag.natt ) { // // add natt draft 00-01 id paylaods // if( ( ph1->tunnel->peer->natt_mode == IPSEC_NATT_ENABLE ) || ( ph1->tunnel->peer->natt_mode == IPSEC_NATT_FORCE_DRAFT ) ) { payload_add_vend( packet, vend_natt_v00, vendpld( vid_count, next ) ); log.txt( LLOG_INFO, "ii : local supports nat-t ( draft v00 )\n" ); payload_add_vend( packet, vend_natt_v01, vendpld( vid_count, next ) ); log.txt( LLOG_INFO, "ii : local supports nat-t ( draft v01 )\n" ); } // // add natt draft 02-rfc id paylaods // if( ( ph1->tunnel->peer->natt_mode == IPSEC_NATT_ENABLE ) || ( ph1->tunnel->peer->natt_mode == IPSEC_NATT_FORCE_RFC ) ) { payload_add_vend( packet, vend_natt_v02, vendpld( vid_count, next ) ); log.txt( LLOG_INFO, "ii : local supports nat-t ( draft v02 )\n" ); payload_add_vend( packet, vend_natt_v03, vendpld( vid_count, next ) ); log.txt( LLOG_INFO, "ii : local supports nat-t ( draft v03 )\n" ); payload_add_vend( packet, vend_natt_rfc, vendpld( vid_count, next ) ); log.txt( LLOG_INFO, "ii : local supports nat-t ( rfc )\n" ); } } // // optionally add fragmentation vendor id payload // if( ph1->vendopts_l.flag.frag ) { payload_add_vend( packet, vend_frag, vendpld( vid_count, next ) ); log.txt( LLOG_INFO, "ii : local supports FRAGMENTATION\n" ); } // // optionally add dpd vendor id payload // if( ph1->vendopts_l.flag.dpdv1 ) { payload_add_vend( packet, vend_dpd1, vendpld( vid_count, next ) ); payload_add_vend( packet, vend_dpd1_ng, vendpld( vid_count, next ) ); log.txt( LLOG_INFO, "ii : local supports DPDv1\n" ); } // // optionally add shrew soft vendor id payload // if( ph1->vendopts_l.flag.ssoft ) { payload_add_vend( packet, vend_ssoft, vendpld( vid_count, next ) ); log.txt( LLOG_INFO, "ii : local is SHREW SOFT compatible\n" ); } // // optionally add netscreen vendor payload // if( ph1->vendopts_l.flag.netsc ) { payload_add_vend( packet, vend_netsc, vendpld( vid_count, next ) ); log.txt( LLOG_INFO, "ii : local is NETSCREEN compatible\n" ); } // // optionally add sidewinder vendor payload // if( ph1->vendopts_l.flag.swind ) { payload_add_vend( packet, vend_swind, vendpld( vid_count, next ) ); log.txt( LLOG_INFO, "ii : local is SIDEWINDER compatible\n" ); } // // optionally add unity vendor id payload // if( ph1->vendopts_l.flag.unity ) { BDATA vend_unity2; vend_unity2.add( vend_unity ); // base vendor id vend_unity2.add( 0x01, 1 ); // major version vend_unity2.add( 0x00, 1 ); // minor version payload_add_vend( packet, vend_unity2, vendpld( vid_count, next ) ); log.txt( LLOG_INFO, "ii : local is CISCO UNITY compatible\n" ); } // // optionally add checkpoint vendor payload ( must be last ) // if( ph1->vendopts_l.flag.chkpt ) { uint32_t prod; uint32_t vers; uint32_t feat; if( ph1->tunnel->peer->contact != IPSEC_CONTACT_CLIENT ) prod = htonl( 1 ); // 01 == gateway else prod = htonl( 2 ); // 02 == client vers = htonl( 5006 ); // NG AI R56 feat = htonl( 0x18800000 ); // all features BDATA vend_chkpt2; vend_chkpt2.add( vend_chkpt ); // base vendor id vend_chkpt2.add( &prod, 4 ); // client vend_chkpt2.add( &vers, 4 ); // version vend_chkpt2.add( 0, 4 ); // timestamp vend_chkpt2.add( 0, 4 ); // reserved vend_chkpt2.add( &feat, 4 ); // features payload_add_vend( packet, vend_chkpt2, vendpld( vid_count, next ) ); log.txt( LLOG_INFO, "ii : local is CHECKPOINT compatible\n" ); } return LIBIKE_OK; } inline bool vendcmp( BDATA & vend1, BDATA & vend2, bool prefix = false ) { if( prefix ) { if( vend1.size() < vend2.size() ) return false; } else { if( vend1.size() != vend2.size() ) return false; } return !memcmp( vend1.buff(), vend2.buff(), vend2.size() ); } long _IKED::phase1_chk_vend( IDB_PH1 * ph1, BDATA & vend ) { // // check for xauth vendor id // if( vendcmp( vend, vend_xauth ) ) { ph1->vendopts_r.flag.xauth = true; log.txt( LLOG_INFO, "ii : peer supports XAUTH\n" ); return LIBIKE_OK; } // // check for fragmentation vendor id // if( vendcmp( vend, vend_frag ) ) { ph1->vendopts_r.flag.frag = true; log.txt( LLOG_INFO, "ii : peer supports FRAGMENTATION\n" ); return LIBIKE_OK; } // // check for dead peer detection vendor id // if( vendcmp( vend, vend_dpd1 ) || vendcmp( vend, vend_dpd1_ng ) ) { ph1->vendopts_r.flag.dpdv1 = true; log.txt( LLOG_INFO, "ii : peer supports DPDv1\n" ); return LIBIKE_OK; } // // check for heartbeat notify detection vendor id // if( vendcmp( vend, vend_hbeat ) ) { ph1->vendopts_r.flag.hbeat = true; log.txt( LLOG_INFO, "ii : peer supports HEARTBEAT-NOTIFY\n" ); return LIBIKE_OK; } // // check for natt v00 vendor id // if( vendcmp( vend, vend_natt_v00 ) ) { if( ( ph1->tunnel->peer->natt_mode == IPSEC_NATT_ENABLE ) || ( ph1->tunnel->peer->natt_mode == IPSEC_NATT_FORCE_DRAFT ) ) { if( ph1->natt_version < IPSEC_NATT_V00 ) { ph1->vendopts_r.flag.natt = true; ph1->natt_version = IPSEC_NATT_V00; ph1->natt_pldtype = ISAKMP_PAYLOAD_NAT_VXX_DISC; } } log.txt( LLOG_INFO, "ii : peer supports nat-t ( draft v00 )\n" ); return LIBIKE_OK; } // // check for natt v01 vendor id // if( vendcmp( vend, vend_natt_v01 ) ) { if( ( ph1->tunnel->peer->natt_mode == IPSEC_NATT_ENABLE ) || ( ph1->tunnel->peer->natt_mode == IPSEC_NATT_FORCE_DRAFT ) ) { if( ph1->natt_version < IPSEC_NATT_V01 ) { ph1->vendopts_r.flag.natt = true; ph1->natt_version = IPSEC_NATT_V01; ph1->natt_pldtype = ISAKMP_PAYLOAD_NAT_VXX_DISC; } } log.txt( LLOG_INFO, "ii : peer supports nat-t ( draft v01 )\n" ); return LIBIKE_OK; } // // check for natt v02 vendor id // if( vendcmp( vend, vend_natt_v02 ) ) { if( ( ph1->tunnel->peer->natt_mode == IPSEC_NATT_ENABLE ) || ( ph1->tunnel->peer->natt_mode == IPSEC_NATT_FORCE_RFC ) ) { if( ph1->natt_version < IPSEC_NATT_V02 ) { ph1->vendopts_r.flag.natt = true; ph1->natt_version = IPSEC_NATT_V02; ph1->natt_pldtype = ISAKMP_PAYLOAD_NAT_VXX_DISC; } } log.txt( LLOG_INFO, "ii : peer supports nat-t ( draft v02 )\n" ); return LIBIKE_OK; } // // check for natt v03 vendor id // if( vendcmp( vend, vend_natt_v03 ) ) { if( ( ph1->tunnel->peer->natt_mode == IPSEC_NATT_ENABLE ) || ( ph1->tunnel->peer->natt_mode == IPSEC_NATT_FORCE_RFC ) ) { if( ph1->natt_version < IPSEC_NATT_V03 ) { ph1->vendopts_r.flag.natt = true; ph1->natt_version = IPSEC_NATT_V03; ph1->natt_pldtype = ISAKMP_PAYLOAD_NAT_VXX_DISC; } } log.txt( LLOG_INFO, "ii : peer supports nat-t ( draft v03 )\n" ); return LIBIKE_OK; } // // check for natt rfc vendor id // if( vendcmp( vend, vend_natt_rfc ) ) { if( ( ph1->tunnel->peer->natt_mode == IPSEC_NATT_ENABLE ) || ( ph1->tunnel->peer->natt_mode == IPSEC_NATT_FORCE_RFC ) ) { ph1->vendopts_r.flag.natt = true; ph1->natt_version = IPSEC_NATT_RFC; ph1->natt_pldtype = ISAKMP_PAYLOAD_NAT_RFC_DISC; } log.txt( LLOG_INFO, "ii : peer supports nat-t ( rfc )\n" ); return LIBIKE_OK; } // // check for shrew soft vendor id // if( vendcmp( vend, vend_ssoft ) ) { ph1->vendopts_r.flag.ssoft = true; ph1->vendopts_r.flag.unity = true; log.txt( LLOG_INFO, "ii : peer is SHREW SOFT compatible\n" ); return LIBIKE_OK; } // // check for kame vendor id // if( vendcmp( vend, vend_kame ) ) { ph1->vendopts_r.flag.kame = true; log.txt( LLOG_INFO, "ii : peer is IPSEC-TOOLS compatible\n" ); return LIBIKE_OK; } // // check for netscreen vendor id // if( vendcmp( vend, vend_netsc ) ) { ph1->vendopts_r.flag.netsc = true; log.txt( LLOG_INFO, "ii : peer is NETSCREEN compatible\n" ); return LIBIKE_OK; } // // check for zywall vendor id // if( vendcmp( vend, vend_zwall ) ) { ph1->vendopts_r.flag.zwall = true; log.txt( LLOG_INFO, "ii : peer is ZYWALL compatible\n" ); return LIBIKE_OK; } // // check for sidewinder vendor id // if( vendcmp( vend, vend_swind ) ) { ph1->vendopts_r.flag.swind = true; log.txt( LLOG_INFO, "ii : peer is SIDEWINDER compatible\n" ); return LIBIKE_OK; } // // check for unity vendor id // if( vendcmp( vend, vend_unity, true ) ) { // // if we are communcating with a // cisco unity device, set the // policy init flag. this forces // a single phase2 SA negotiation // for the first policy created // ph1->tunnel->tstate |= TSTATE_POLICY_INIT; ph1->vendopts_r.flag.unity = true; log.txt( LLOG_INFO, "ii : peer is CISCO UNITY compatible\n" ); return LIBIKE_OK; } // // check for checkpoint vendor id // if( vendcmp( vend, vend_chkpt, true ) ) { ph1->vendopts_r.flag.chkpt = true; log.txt( LLOG_INFO, "ii : peer is CHECKPOINT compatible\n" ); return LIBIKE_OK; } log.bin( LLOG_DEBUG, LLOG_DEBUG, vend.buff(), vend.size(), "ii : unknown vendor id" ); return LIBIKE_OK; } long _IKED::phase1_chk_hash( IDB_PH1 * ph1 ) { // // generate hash data for comparison // BDATA hash_c; if( ph1->initiator ) { phase1_gen_hash_r( ph1, hash_c ); log.bin( LLOG_DEBUG, LLOG_DECODE, ph1->hash_r.buff(), hash_c.size(), "== : phase1 hash_r ( received )" ); } else { phase1_gen_hash_i( ph1, hash_c ); log.bin( LLOG_DEBUG, LLOG_DECODE, ph1->hash_r.buff(), hash_c.size(), "== : phase1 hash_i ( received )" ); } char txtaddr_l[ LIBIKE_MAX_TEXTADDR ]; char txtaddr_r[ LIBIKE_MAX_TEXTADDR ]; text_addr( txtaddr_l, &ph1->tunnel->saddr_l, true ); text_addr( txtaddr_r, &ph1->tunnel->saddr_r, true ); if( hash_c != ph1->hash_r ) { log.txt( LLOG_INFO, "!! : phase1 sa rejected, invalid auth data\n" "!! : %s <-> %s\n" "!! : %04x%04x:%04x%04x\n", txtaddr_l, txtaddr_r, htonl( *( long * ) &ph1->cookies.i[ 0 ] ), htonl( *( long * ) &ph1->cookies.i[ 4 ] ), htonl( *( long * ) &ph1->cookies.r[ 0 ] ), htonl( *( long * ) &ph1->cookies.r[ 4 ] ) ); return LIBIKE_FAILED; } log.txt( LLOG_INFO, "ii : phase1 sa established\n" "ii : %s <-> %s\n" "ii : %04x%04x:%04x%04x\n", txtaddr_r, txtaddr_l, htonl( *( long * ) &ph1->cookies.i[ 0 ] ), htonl( *( long * ) &ph1->cookies.i[ 4 ] ), htonl( *( long * ) &ph1->cookies.r[ 0 ] ), htonl( *( long * ) &ph1->cookies.r[ 4 ] ) ); return LIBIKE_OK; } long _IKED::phase1_chk_sign( IDB_PH1 * ph1 ) { // // verify the peer certificates // using the ca cert specified // in the peer configuration // BDATA cert; if( !cert_verify( ph1->certs_r, ph1->tunnel->peer->cert_r, cert ) ) { log.txt( LLOG_ERROR, "!! : unable to verify remote peer certificate\n" ); return LIBIKE_FAILED; } // // read the public key from the // peer provided certificate // BDATA pubkey; if( !pubkey_rsa_read( cert, pubkey ) ) { log.txt( LLOG_ERROR, "!! : unable to extract public key from remote peer certificate\n" ); return LIBIKE_FAILED; } // // use the public key to decrypt // the signiature data provided // by the remote peer // if( !pubkey_rsa_decrypt( pubkey, ph1->sign_r, ph1->hash_r ) ) { log.txt( LLOG_ERROR, "!! : unable to compute remote peer signed hash\n" ); return LIBIKE_FAILED; } // // check hash value // return phase1_chk_hash( ph1 ); } long _IKED::phase1_gen_natd( IDB_PH1 * ph1 ) { if( ph1->lstate & LSTATE_GENNATD ) return LIBIKE_OK; BDATA natd; if( !natd.size( ph1->hash_size ) ) return LIBIKE_MEMORY; // // compute the nat discovery // hash for remote address // EVP_MD_CTX ctx_hash; EVP_DigestInit( &ctx_hash, ph1->evp_hash ); EVP_DigestUpdate( &ctx_hash, ph1->cookies.i, ISAKMP_COOKIE_SIZE ); EVP_DigestUpdate( &ctx_hash, ph1->cookies.r, ISAKMP_COOKIE_SIZE ); EVP_DigestUpdate( &ctx_hash, &ph1->tunnel->saddr_r.saddr4.sin_addr.s_addr, 4 ); EVP_DigestUpdate( &ctx_hash, &ph1->tunnel->saddr_r.saddr4.sin_port, 2 ); EVP_DigestFinal( &ctx_hash, natd.buff(), NULL ); EVP_MD_CTX_cleanup( &ctx_hash ); ph1->natd_hash_l.add( natd ); // // compute the nat discovery // hash for local address // EVP_DigestInit( &ctx_hash, ph1->evp_hash ); EVP_DigestUpdate( &ctx_hash, ph1->cookies.i, ISAKMP_COOKIE_SIZE ); EVP_DigestUpdate( &ctx_hash, ph1->cookies.r, ISAKMP_COOKIE_SIZE ); EVP_DigestUpdate( &ctx_hash, &ph1->tunnel->saddr_l.saddr4.sin_addr.s_addr, 4 ); EVP_DigestUpdate( &ctx_hash, &ph1->tunnel->saddr_l.saddr4.sin_port, 2 ); EVP_DigestFinal( &ctx_hash, natd.buff(), NULL ); EVP_MD_CTX_cleanup( &ctx_hash ); ph1->natd_hash_l.add( natd ); ph1->lstate |= LSTATE_GENNATD; return LIBIKE_OK; } bool _IKED::phase1_add_natd( IDB_PH1 * ph1, PACKET_IKE & packet, uint8_t next ) { BDATA natd; long index = 0; long count = ph1->natd_hash_l.count(); for( long index = 0; index < count; index++ ) { ph1->natd_hash_l.get( natd, index ); if( index < ( count - 1 ) ) payload_add_natd( packet, natd, ph1->natt_pldtype ); else payload_add_natd( packet, natd, next ); } return true; } bool _IKED::phase1_chk_natd( IDB_PH1 * ph1 ) { // // if we are rekeying, skip this // if( ph1->tunnel->lstate & TSTATE_NATT_FLOAT ) return true; // // verify that both support natt // switch( ph1->tunnel->peer->natt_mode ) { case IPSEC_NATT_DISABLE: log.txt( LLOG_INFO, "ii : nat-t is disabled locally\n" ); break; case IPSEC_NATT_ENABLE: { bool xlated_l = true; bool xlated_r = true; BDATA natd_l; BDATA natd_r; // // make sure remote peer negotiated natt // if( !ph1->natt_version ) { log.txt( LLOG_INFO, "ii : nat-t is unsupported by remote peer\n" ); break; } // // make sure local nat discovery hashes // have been generated // phase1_gen_natd( ph1 ); // // compare the remote destination // hash to all local source hashes // if( !ph1->natd_hash_r.get( natd_r, 0 ) ) { log.txt( LLOG_ERROR, "!! : no remote desitnation hash available for comparison\n" ); break; } for( long index = 1; index < ph1->natd_hash_l.count(); index++ ) { ph1->natd_hash_l.get( natd_l, index ); if( natd_r == natd_l ) { xlated_l = false; break; } } if( xlated_l ) log.txt( LLOG_INFO, "ii : nat discovery - local address is translated\n" ); // // compare the local destination // hash to all remote source hashes // if( !ph1->natd_hash_l.get( natd_l, 0 ) ) { log.txt( LLOG_ERROR, "!! : no local desitnation hash available for comparison\n" ); break; } for( long index = 1; index < ph1->natd_hash_r.count(); index++ ) { ph1->natd_hash_r.get( natd_r, index ); if( natd_l == natd_r ) { xlated_r = false; break; } } if( xlated_r ) log.txt( LLOG_INFO, "ii : nat discovery - remote address is translated\n" ); // // only set the nat-t port if translation was detected // if( xlated_l || xlated_r ) { ph1->tunnel->natt_version = ph1->natt_version; break; } log.txt( LLOG_INFO, "ii : disabled nat-t ( no nat detected )\n" ); break; } case IPSEC_NATT_FORCE_DRAFT: log.txt( LLOG_INFO, "ii : forcing nat-t to enabled ( draft )\n" ); // // set natt to negotiated version or draft v00 // if( ph1->natt_version != IPSEC_NATT_NONE ) ph1->tunnel->natt_version = ph1->natt_version; else ph1->tunnel->natt_version = IPSEC_NATT_V00; break; case IPSEC_NATT_FORCE_RFC: log.txt( LLOG_INFO, "ii : forcing nat-t to enabled ( rfc )\n" ); // // set natt to negotiated version or rfc // if( ph1->natt_version != IPSEC_NATT_NONE ) ph1->tunnel->natt_version = ph1->natt_version; else ph1->tunnel->natt_version = IPSEC_NATT_RFC; break; case IPSEC_NATT_FORCE_CISCO: log.txt( LLOG_INFO, "ii : forcing nat-t to cisco-udp\n" ); // // set natt to cisco-udp // ph1->tunnel->natt_version = IPSEC_NATT_CISCO; break; } // // switch to natt ports if required // ph1->tunnel->lstate |= TSTATE_NATT_FLOAT; if( ph1->tunnel->natt_version >= IPSEC_NATT_V02 ) { // // switch our local port to natt // if( socket_lookup_port( ph1->tunnel->saddr_l, true ) != LIBIKE_OK ) { log.txt( LLOG_INFO, "ii : unable to locate local nat-t udp port\n" ); return false; } log.txt( LLOG_INFO, "ii : switching to src nat-t udp port %u\n", ntohs( ph1->tunnel->saddr_l.saddr4.sin_port ) ); // // switch the peer port to natt // ph1->tunnel->saddr_r.saddr4.sin_port = ph1->tunnel->peer->natt_port; log.txt( LLOG_INFO, "ii : switching to dst nat-t udp port %u\n", ntohs( ph1->tunnel->saddr_r.saddr4.sin_port ) ); // // setup our filter // #ifdef WIN32 iked.tunnel_filter_add( ph1->tunnel, true ); #endif return true; } return false; } bool _IKED::phase1_chk_port( IDB_PH1 * ph1, IKE_SADDR * saddr_r, IKE_SADDR * saddr_l ) { // // check if our peer has floated ports // if( saddr_r->saddr4.sin_port != ph1->tunnel->saddr_r.saddr4.sin_port ) { if( ph1->initiator ) { if( ph1->tunnel->peer->natt_mode == IPSEC_NATT_NONE ) { log.txt( LLOG_INFO, "ii : initiator port values floated but nat-t is disabled\n" ); return false; } if( ph1->tunnel->lstate & TSTATE_NATT_FLOAT ) { log.txt( LLOG_INFO, "ww : initiator port values should only float once per session\n" ); return true; } } else { log.txt( LLOG_DEBUG, "ii : responder port values have floated\n" ); } // // float our port to natt // ph1->tunnel->saddr_l.saddr4.sin_port = saddr_l->saddr4.sin_port; // // float the peer port to natt // ph1->tunnel->saddr_r.saddr4.sin_port = saddr_r->saddr4.sin_port; // // switch the tunnel to the // negotiated natt version // ph1->tunnel->natt_version = ph1->natt_version; log.txt( LLOG_INFO, "ii : floating to nat-t udp ports %u -> %u\n", ntohs( ph1->tunnel->saddr_r.saddr4.sin_port ), ntohs( ph1->tunnel->saddr_l.saddr4.sin_port ) ); // // setup our filter // #ifdef WIN32 iked.tunnel_filter_add( ph1->tunnel, true ); #endif ph1->tunnel->lstate |= TSTATE_NATT_FLOAT; } return true; } long _IKED::phase1_chk_idr( IDB_PH1 * ph1 ) { // // create a phase1 remote id based // on our tunnel configuration data // IKE_PH1ID idt; if( !gen_ph1id_r( ph1, idt ) ) return LIBIKE_FAILED; // // compare the id values // if( !cmp_ph1id( idt, ph1->ph1id_r, ph1->vendopts_l.flag.natt ) ) return LIBIKE_FAILED; return LIBIKE_OK; } ike-2.2.1+dfsg/source/iked/ike.exch.phase2.cpp000066400000000000000000001153241223036517100210100ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "iked.h" long _IKED::process_phase2_recv( IDB_PH1 * ph1, PACKET_IKE & packet, unsigned char payload ) { long result = LIBIKE_OK; // // log packet type // log.txt( LLOG_INFO, "ii : processing phase2 packet ( %i bytes )\n", packet.size() ); // // attempt to locate a known // sa for this message id // uint32_t msgid = packet.get_msgid(); IDB_PH2 * ph2 = NULL; if( !idb_list_ph2.find( true, &ph2, ph1->tunnel, XCH_STATUS_ANY, XCH_STATUS_ANY, NULL, &msgid, NULL, NULL ) ) { // // looks like a unique phase 2 // session, allocate a new sa // ph2 = new IDB_PH2( ph1->tunnel, false, msgid, 0 ); ph2->add( true ); // // calculate iv for this // pahse2 exchange // ph2->new_msgiv( ph1 ); // // make sure we respond using the // isakmp sa that was last seen // ph2->cookies = ph1->cookies; } // // make sure we are not dealing // with an sa marked for death // if( ph1->status() == XCH_STATUS_DEAD ) { log.txt( LLOG_ERROR, "!! : phase2 packet ignored ( phase1 marked for death )\n" ); ph2->dec( true ); return LIBIKE_OK; } if( ph2->status() == XCH_STATUS_DEAD ) { log.txt( LLOG_ERROR, "!! : phase2 packet ignored ( phase2 marked for death )\n" ); ph2->dec( true ); return LIBIKE_OK; } // // make sure we are not dealing // whith an imature phase1 sa // if( ph1->status() < XCH_STATUS_MATURE ) { log.txt( LLOG_ERROR, "!! : config packet ignored ( phase1 not mature )\n" ); ph2->dec( true ); return LIBIKE_OK; } // // make sure we are not dealing // with a mature sa // if( ph2->status() >= XCH_STATUS_MATURE ) { log.txt( LLOG_ERROR, "!! : phase2 packet ignored, resending last packet ( phase2 already mature )\n" ); ph2->resend(); ph2->dec( true ); return LIBIKE_OK; } // // attempt to decrypt our packet // if( packet_ike_decrypt( ph1, packet, &ph2->iv ) != LIBIKE_OK ) { log.txt( LLOG_ERROR, "!! : phase2 packet ignored, resending last packet ( packet decryption error )\n" ); ph2->resend(); ph2->dec( true ); return LIBIKE_OK; } // // if we are dumping decrypted packets, // we need to rebuild a full packet to // dump to pcap format // if( dump_decrypt ) { // // strip the isakmp encryption flag // packet.buff()[ ISAKMP_FLAGS_OFFSET ] &= ~ISAKMP_FLAG_ENCRYPT; // // build ip dump packet // PACKET_IP packet_ip_dump; packet_ike_encap( packet, packet_ip_dump, ph1->tunnel->saddr_r, ph1->tunnel->saddr_l, ph1->tunnel->natt_version ); // // obtain ethernet header // ETH_HEADER ethhdr; header( packet_ip_dump, ethhdr ); // // dump the packet // pcap_decrypt.dump( ethhdr, packet_ip_dump ); } /* // // read and validate the hash // if( !packet.get_payload( false, payload ) ) { log.txt( LLOG_ERROR, "!! : phase2 packet ignored ( invalid hash payload )\n" ); ph2->dec( true ); return LIBIKE_OK; } if( payload_get_hash( packet, ph2->hash_r, ph1->hash_size ) != LIBIKE_OK ) { log.txt( LLOG_ERROR, "!! : phase2 packet ignored ( invalid hash value )\n" ); ph2->dec( true ); return LIBIKE_OK; } // // populate hash data accumulator // ph2->hda.size( 0 ); ph2->hda.add( packet.buff() + packet.oset(), packet.size() - packet.oset() ); if( ph2->initiator ) { // // check responders hash // if( !( ph2->xstate & XSTATE_RECV_HA ) ) { // // quick mode hash // if( phase2_chk_hash_r( ph1, ph2 ) != LIBIKE_OK ) packet.notify = ISAKMP_N_INVALID_HASH_INFORMATION; ph2->xstate |= XSTATE_RECV_HA; // ph2->lstate |= LSTATE_CHKHASH; } } else { // // check initiators hash // if( !( ph2->xstate & XSTATE_RECV_HA ) ) { // // quick mode hash // if( phase2_chk_hash_i( ph1, ph2 ) != LIBIKE_OK ) packet.notify = ISAKMP_N_INVALID_HASH_INFORMATION; ph2->xstate |= XSTATE_RECV_HA; // ph2->lstate |= LSTATE_CHKHASH; } else { // // livliness proof hash // if( phase2_chk_hash_p( ph1, ph2 ) != LIBIKE_OK ) packet.notify = ISAKMP_N_INVALID_HASH_INFORMATION; ph2->xstate |= XSTATE_RECV_LP; } } */ // // read and process all payloads // ph2->hda.del( true ); uint8_t next_payload; while( payload != ISAKMP_PAYLOAD_NONE ) { // // read the payload header // if( !packet.get_payload( false, next_payload ) ) break; // // check the payload type // switch( payload ) { // // read the hash payload // case ISAKMP_PAYLOAD_HASH: { if( ( ph2->xstate & XSTATE_RECV_HA ) && ( ph2->xstate & XSTATE_RECV_LP ) ) log.txt( LLOG_INFO, "<< : ignoring duplicate hash payload\n" ); else { result = payload_get_hash( packet, ph2->hash_r, ph1->hash_size ); if( !( ph2->xstate & XSTATE_RECV_HA ) ) ph2->xstate |= XSTATE_RECV_HA; else ph2->xstate |= XSTATE_RECV_LP; } break; } // // security association payload // case ISAKMP_PAYLOAD_SA: { if( ph2->xstate & XSTATE_RECV_SA ) log.txt( LLOG_INFO, "<< : ignoring duplicate security association payload\n" ); else { size_t beg = packet.oset() - 4; result = payload_get_sa( packet, ph2->plist_r ); size_t end = packet.oset(); ph2->hda.add( packet.buff() + beg, end - beg ); } ph2->xstate |= XSTATE_RECV_SA; break; } // // nonce payload // case ISAKMP_PAYLOAD_NONCE: { if( ph2->xstate & XSTATE_RECV_NO ) log.txt( LLOG_INFO, "<< : ignoring duplicate nonce payload\n" ); else { size_t beg = packet.oset() - 4; result = payload_get_nonce( packet, ph2->nonce_r ); size_t end = packet.oset(); ph2->hda.add( packet.buff() + beg, end - beg ); } ph2->xstate |= XSTATE_RECV_NO; break; } // // identity payload // case ISAKMP_PAYLOAD_IDENT: { if( ph2->initiator ) { if( !( ph2->xstate & XSTATE_RECV_IDL ) ) { size_t beg = packet.oset() - 4; result = payload_get_ph2id( packet, ph2->ph2id_rd ); size_t end = packet.oset(); ph2->hda.add( packet.buff() + beg, end - beg ); ph2->xstate |= XSTATE_RECV_IDL; break; } if( !( ph2->xstate & XSTATE_RECV_IDR ) ) { size_t beg = packet.oset() - 4; result = payload_get_ph2id( packet, ph2->ph2id_rs ); size_t end = packet.oset(); ph2->hda.add( packet.buff() + beg, end - beg ); ph2->xstate |= XSTATE_RECV_IDR; break; } } else { if( !( ph2->xstate & XSTATE_RECV_IDR ) ) { size_t beg = packet.oset() - 4; result = payload_get_ph2id( packet, ph2->ph2id_rs ); size_t end = packet.oset(); ph2->hda.add( packet.buff() + beg, end - beg ); ph2->xstate |= XSTATE_RECV_IDR; break; } if( !( ph2->xstate & XSTATE_RECV_IDL ) ) { size_t beg = packet.oset() - 4; result = payload_get_ph2id( packet, ph2->ph2id_rd ); size_t end = packet.oset(); ph2->hda.add( packet.buff() + beg, end - beg ); ph2->xstate |= XSTATE_RECV_IDL; break; } } if( ( ph2->xstate & XSTATE_RECV_IDR ) && ( ph2->xstate & XSTATE_RECV_IDL ) ) log.txt( LLOG_INFO, "<< : ignoring duplicate id payload\n" ); break; } // // key exchange payload // case ISAKMP_PAYLOAD_KEX: { if( ph2->xstate & XSTATE_RECV_KE ) log.txt( LLOG_INFO, "<< : ignoring duplicate key excahnge payload\n" ); else { size_t beg = packet.oset() - 4; result = payload_get_kex( packet, ph2->xr ); size_t end = packet.oset(); ph2->hda.add( packet.buff() + beg, end - beg ); } ph2->xstate |= XSTATE_RECV_KE; break; } // // natt original address ( ignored ) // case ISAKMP_PAYLOAD_NAT_VXX_ORIG: case ISAKMP_PAYLOAD_NAT_RFC_ORIG: { log.txt( LLOG_INFO, "<< : natt original address\n" ); size_t beg = packet.oset() - 4; packet.get_null( packet.get_payload_left() ); size_t end = packet.oset(); ph2->hda.add( packet.buff() + beg, end - beg ); break; } // // notify payload // case ISAKMP_PAYLOAD_NOTIFY: { IKE_NOTIFY notify; size_t beg = packet.oset() - 4; result = payload_get_notify( packet, ¬ify ); size_t end = packet.oset(); ph2->hda.add( packet.buff() + beg, end - beg ); if( result == LIBIKE_OK ) ph2->notifications.add( notify ); break; } // // unhandled payload // default: log.txt( LLOG_ERROR, "!! : unhandled phase2 payload \'%s\' ( %i )\n", find_name( NAME_PAYLOAD, payload ), payload ); packet.notify = ISAKMP_N_INVALID_PAYLOAD_TYPE; result = LIBIKE_DECODE; break; } // // check that the entire payload was read // if( packet.get_payload_left() ) log.txt( LLOG_ERROR, "!! : unprocessed payload data !!!\n" ); // // check the final paylaod process result // if( result != LIBIKE_OK ) { ph2->status( XCH_STATUS_DEAD, XCH_FAILED_MSG_FORMAT, packet.notify ); ph2->dec( true ); return result; } // // read next payload // payload = next_payload; } // // now that all payloads have been read, // validate any received hash, peer id // and proposal payloads // while( true ) { if( ph2->initiator ) { // // check responders quick mode hash // if( ( ph2->status() < XCH_STATUS_MATURE ) && ( ph2->xstate & XSTATE_RECV_HA ) && ( ph2->xstate & XSTATE_RECV_SA ) && ( ph2->xstate & XSTATE_RECV_NO ) ) { result = phase2_chk_hash_r( ph1, ph2 ); if( result != LIBIKE_OK ) { packet.notify = ISAKMP_N_INVALID_HASH_INFORMATION; break; } ph2->lstate |= LSTATE_CHKHASH; // // validate that the remote ids // match the ids proposed by us // result = phase2_chk_params( ph1, ph2, packet ); if( result != LIBIKE_OK ) break; // // log result // char txtaddr_l[ LIBIKE_MAX_TEXTADDR ]; char txtaddr_r[ LIBIKE_MAX_TEXTADDR ]; text_addr( txtaddr_l, &ph1->tunnel->saddr_l, true ); text_addr( txtaddr_r, &ph1->tunnel->saddr_r, true ); log.txt( LLOG_INFO, "ii : phase2 sa established\n" "ii : %s <-> %s\n", txtaddr_l, txtaddr_r ); ph2->lstate |= LSTATE_CHKIDS; } } else { // // check initiators quick mode hash // if( ( ph2->xstate & XSTATE_RECV_HA ) && ( ph2->xstate & XSTATE_RECV_SA ) && ( ph2->xstate & XSTATE_RECV_NO ) && !( ph2->lstate & LSTATE_CHKHASH ) ) { result = phase2_chk_hash_i( ph1, ph2 ); if( result != LIBIKE_OK ) { packet.notify = ISAKMP_N_INVALID_HASH_INFORMATION; break; } ph2->lstate |= LSTATE_CHKHASH; // // verify the peer ids against // the local policy database // and acquire spis // result = phase2_chk_params( ph1, ph2, packet ); if( result != LIBIKE_OK ) break; ph2->lstate |= LSTATE_CHKIDS; } // // check initiators liveliness proof hash // if( ( ph2->status() < XCH_STATUS_MATURE ) && ( ph2->xstate & XSTATE_RECV_LP ) ) { result = phase2_chk_hash_p( ph1, ph2 ); if( result != LIBIKE_OK ) { packet.notify = ISAKMP_N_INVALID_HASH_INFORMATION; break; } else { // // generate our keys // phase2_gen_keys( ph1, ph2 ); // // log result // char txtaddr_l[ LIBIKE_MAX_TEXTADDR ]; char txtaddr_r[ LIBIKE_MAX_TEXTADDR ]; text_addr( txtaddr_l, &ph1->tunnel->saddr_l, true ); text_addr( txtaddr_r, &ph1->tunnel->saddr_r, true ); log.txt( LLOG_INFO, "ii : phase2 sa established\n" "ii : %s <-> %s\n", txtaddr_l, txtaddr_r ); ph2->status( XCH_STATUS_MATURE, XCH_NORMAL, 0 ); ph2->clean(); } } } break; } // // check the peer payload results // if( result != LIBIKE_OK ) { ph2->status( XCH_STATUS_DEAD, XCH_FAILED_MSG_FORMAT, packet.notify ); ph2->dec( true ); return result; } // // now build and send any response // packets that may be necessary // // NOTE : responder packets are only // sent via the pfkey thread after an // outbound SPI is received // if( ph2->initiator && ( ph1->status() != XCH_STATUS_DEAD ) && ( ph2->status() < XCH_STATUS_MATURE ) ) process_phase2_send( ph1, ph2 ); // // cleanup // ph2->dec( true ); return LIBIKE_OK; } long _IKED::process_phase2_send( IDB_PH1 * ph1, IDB_PH2 * ph2 ) { // // quick mode initiator // if( ph2->initiator ) { if( !( ph2->xstate & XSTATE_SENT_HA ) ) { // // hash + sa + nonce [ + ke ] + idi + idr packet // PACKET_IKE packet; packet.set_msgid( ph2->msgid ); packet.write( ph1->cookies, ISAKMP_PAYLOAD_HASH, ISAKMP_EXCH_QUICK, ISAKMP_FLAG_ENCRYPT ); size_t off = packet.size(); ph2->hash_l.size( ph1->hash_size ); payload_add_hash( packet, ph2->hash_l, ISAKMP_PAYLOAD_SA ); size_t beg = packet.size(); payload_add_sa( packet, ph2->plist_l, ISAKMP_PAYLOAD_NONCE ); // // if we are using pfs, the payload // order changes to include a kex // // NOTE : if nonce is omitted, // racoon crashes // unsigned char next = ISAKMP_PAYLOAD_IDENT; if( ph2->dhgr_id ) next = ISAKMP_PAYLOAD_KEX; payload_add_nonce( packet, ph2->nonce_l, next ); if( ph2->dhgr_id ) payload_add_kex( packet, ph2->xl, ISAKMP_PAYLOAD_IDENT ); payload_add_ph2id( packet, ph2->ph2id_ls, ISAKMP_PAYLOAD_IDENT ); payload_add_ph2id( packet, ph2->ph2id_ld, ISAKMP_PAYLOAD_NONE ); packet.done(); size_t end = packet.size(); ph2->hda.set( packet.buff() + beg, end - beg ); // // calculate quick mode hash // phase2_gen_hash_i( ph1, ph2, ph2->hash_l ); memcpy( packet.buff() + off + 4, ph2->hash_l.buff(), ph1->hash_size ); // // calculate iv for this // pahse2 exchange // ph2->new_msgiv( ph1 ); // // send packet // packet_ike_send( ph1, ph2, packet, true ); // // update sa state // ph2->xstate |= XSTATE_SENT_HA; ph2->xstate |= XSTATE_SENT_SA; ph2->xstate |= XSTATE_SENT_NO; } // // hash packet ( livliness proof ) // if( ( ph2->xstate & XSTATE_RECV_HA ) && ( ph2->xstate & XSTATE_RECV_SA ) && ( ph2->xstate & XSTATE_RECV_NO ) && !( ph2->xstate & XSTATE_SENT_LP ) ) { // // calculate livliness proof hash // BDATA hash; phase2_gen_hash_p( ph1, ph2, hash ); // // build packet // PACKET_IKE packet; packet.set_msgid( ph2->msgid ); packet.write( ph1->cookies, ISAKMP_PAYLOAD_HASH, ISAKMP_EXCH_QUICK, ISAKMP_FLAG_ENCRYPT ); payload_add_hash( packet, hash, ISAKMP_PAYLOAD_NONE ); packet.done(); // // send packet // packet_ike_send( ph1, ph2, packet, false ); // // generate our keys // phase2_gen_keys( ph1, ph2 ); // // update sa state // ph2->xstate |= XSTATE_SENT_LP; ph2->status( XCH_STATUS_MATURE, XCH_NORMAL, 0 ); ph2->clean(); } } // // quick mode responder // if( !ph2->initiator ) { // // hash + sa + nonce [ + ke ] + idi + idr packet // if( ( ph2->xstate & XSTATE_RECV_HA ) && ( ph2->xstate & XSTATE_RECV_SA ) && ( ph2->xstate & XSTATE_RECV_NO ) && !( ph2->xstate & XSTATE_SENT_HA ) ) { // // build packet // PACKET_IKE packet; packet.set_msgid( ph2->msgid ); packet.write( ph1->cookies, ISAKMP_PAYLOAD_HASH, ISAKMP_EXCH_QUICK, ISAKMP_FLAG_ENCRYPT ); size_t off = packet.size(); ph2->hash_l.size( ph1->hash_size ); payload_add_hash( packet, ph2->hash_l, ISAKMP_PAYLOAD_SA ); size_t beg = packet.size(); payload_add_sa( packet, ph2->plist_l, ISAKMP_PAYLOAD_NONCE ); // // if we are using pfs, the payload // order changes to include a kex // // NOTE : if nonce is omitted, // racoon crashes // unsigned char next = ISAKMP_PAYLOAD_IDENT; if( ph2->dhgr_id ) next = ISAKMP_PAYLOAD_KEX; payload_add_nonce( packet, ph2->nonce_l, next ); if( ph2->dhgr_id ) payload_add_kex( packet, ph2->xl, ISAKMP_PAYLOAD_IDENT ); payload_add_ph2id( packet, ph2->ph2id_ld, ISAKMP_PAYLOAD_IDENT ); // // if we are claiming the lifetime, // the payload order changes to include // a notification payload // next = ISAKMP_PAYLOAD_NONE; if( ph2->lstate & LSTATE_CLAIMLT ) next = ISAKMP_PAYLOAD_NOTIFY; payload_add_ph2id( packet, ph2->ph2id_ls, next ); // // possibly add reponder lifetime // payloads for all proposals // if( ph2->lstate & LSTATE_CLAIMLT ) { IKE_PROPOSAL * proposal; long pindex = 0; long pcount = ph2->plist_l.count(); for( ; pindex < pcount; pindex++ ) { ph2->plist_l.get( &proposal, pindex ); unsigned long lval = htonl( proposal->life_sec ); IKE_NOTIFY notify; notify.type = ISAKMP_PAYLOAD_NOTIFY; notify.doi = ISAKMP_DOI_IPSEC; notify.proto = proposal->proto; notify.code = ISAKMP_N_RESPONDER_LIFETIME; notify.spi = proposal->spi; PACKET_IKE temp; IKE_ATTR attrib; attrib.atype = ISAKMP_ATTR_LIFE_TYPE; attrib.basic = true; attrib.bdata = IKE_LIFE_TYPE_SECONDS; payload_add_attr( temp, attrib ); attrib.atype = ISAKMP_ATTR_LIFE_DURATION; attrib.basic = false; attrib.vdata.set( &lval, sizeof( lval ) ); payload_add_attr( temp, attrib ); notify.data.set( temp ); unsigned char next = ISAKMP_PAYLOAD_NONE; if( ( pcount - pindex ) > 1 ) next = ISAKMP_PAYLOAD_NOTIFY; payload_add_notify( packet, ¬ify, next ); } } packet.done(); size_t end = packet.size(); ph2->hda.del(); ph2->hda.set( packet.buff() + beg, end - beg ); // // calculate quick mode hash // phase2_gen_hash_r( ph1, ph2, ph2->hash_l ); memcpy( packet.buff() + off + 4, ph2->hash_l.buff(), ph2->hash_l.size() ); // // send packet // packet_ike_send( ph1, ph2, packet, false ); // // update sa state // ph2->xstate |= XSTATE_SENT_HA; ph2->xstate |= XSTATE_SENT_SA; ph2->xstate |= XSTATE_SENT_NO; } } return LIBIKE_OK; } long _IKED::phase2_gen_hash_i( IDB_PH1 * ph1, IDB_PH2 * ph2, BDATA & hash ) { BDATA input; input.add( &ph2->msgid, sizeof( ph2->msgid ) ); input.add( ph2->hda ); log.bin( LLOG_DEBUG, LLOG_DECODE, input.buff(), input.size(), "== : phase2 hash_i ( input )" ); hash.size( ph1->hash_size ); HMAC_CTX ctx_prf; HMAC_CTX_init( &ctx_prf ); HMAC_Init_ex( &ctx_prf, ph1->skeyid_a.buff(), ( int ) ph1->skeyid_a.size(), ph1->evp_hash, NULL ); HMAC_Update( &ctx_prf, input.buff(), input.size() ); HMAC_Final( &ctx_prf, hash.buff(), NULL ); HMAC_CTX_cleanup( &ctx_prf ); log.bin( LLOG_DEBUG, LLOG_DECODE, hash.buff(), hash.size(), "== : phase2 hash_i ( computed )" ); return LIBIKE_OK; } long _IKED::phase2_gen_hash_r( IDB_PH1 * ph1, IDB_PH2 * ph2, BDATA & hash ) { BDATA input; input.add( &ph2->msgid, sizeof( ph2->msgid ) ); if( ph2->initiator ) input.add( ph2->nonce_l ); else input.add( ph2->nonce_r ); input.add( ph2->hda ); log.bin( LLOG_DEBUG, LLOG_DECODE, input.buff(), input.size(), "== : phase2 hash_r ( input )" ); hash.size( ph1->hash_size ); HMAC_CTX ctx_prf; HMAC_CTX_init( &ctx_prf ); HMAC_Init_ex( &ctx_prf, ph1->skeyid_a.buff(), ( int ) ph1->skeyid_a.size(), ph1->evp_hash, NULL ); HMAC_Update( &ctx_prf, input.buff(), input.size() ); HMAC_Final( &ctx_prf, hash.buff(), NULL ); HMAC_CTX_cleanup( &ctx_prf ); log.bin( LLOG_DEBUG, LLOG_DECODE, hash.buff(), hash.size(), "== : phase2 hash_r ( computed )" ); return LIBIKE_OK; } long _IKED::phase2_gen_hash_p( IDB_PH1 * ph1, IDB_PH2 * ph2, BDATA & hash ) { BDATA input; input.add( 0, 1 ); input.add( &ph2->msgid, sizeof( ph2->msgid ) ); if( ph2->initiator ) { input.add( ph2->nonce_l ); input.add( ph2->nonce_r ); } else { input.add( ph2->nonce_r ); input.add( ph2->nonce_l ); } log.bin( LLOG_DEBUG, LLOG_DECODE, input.buff(), input.size(), "== : phase2 hash_p ( input )" ); hash.size( ph1->hash_size ); HMAC_CTX ctx_prf; HMAC_CTX_init( &ctx_prf ); HMAC_Init_ex( &ctx_prf, ph1->skeyid_a.buff(), ( int ) ph1->skeyid_a.size(), ph1->evp_hash, NULL ); HMAC_Update( &ctx_prf, input.buff(), input.size() ); HMAC_Final( &ctx_prf, hash.buff(), 0 ); HMAC_CTX_cleanup( &ctx_prf ); log.bin( LLOG_DEBUG, LLOG_DECODE, hash.buff(), hash.size(), "== : phase2 hash_p ( computed )" ); return LIBIKE_OK; } long _IKED::phase2_chk_hash_i( IDB_PH1 * ph1, IDB_PH2 * ph2 ) { // // generate hash data for comparison // BDATA hash_c; phase2_gen_hash_i( ph1, ph2, hash_c ); log.bin( LLOG_DEBUG, LLOG_DECODE, ph2->hash_r.buff(), ph2->hash_r.size(), "== : phase2 hash_i ( received )" ); // // build text strings for logging // char txtaddr_l[ LIBIKE_MAX_TEXTADDR ]; char txtaddr_r[ LIBIKE_MAX_TEXTADDR ]; text_addr( txtaddr_l, &ph1->tunnel->saddr_l, true ); text_addr( txtaddr_r, &ph1->tunnel->saddr_r, true ); // // compare hash data // if( ph2->hash_r != hash_c ) { log.txt( LLOG_ERROR, "!! : phase2 sa rejected, initiator quick mode hash invalid\n" "!! : %s <-> %s\n", txtaddr_l, txtaddr_r ); return LIBIKE_FAILED; } return LIBIKE_OK; } long _IKED::phase2_chk_hash_r( IDB_PH1 * ph1, IDB_PH2 * ph2 ) { // // generate hash data for comparison // BDATA hash_c; phase2_gen_hash_r( ph1, ph2, hash_c ); log.bin( LLOG_DEBUG, LLOG_DECODE, ph2->hash_r.buff(), ph2->hash_r.size(), "== : phase2 hash_r ( received )" ); // // build text strings for logging // char txtaddr_l[ LIBIKE_MAX_TEXTADDR ]; char txtaddr_r[ LIBIKE_MAX_TEXTADDR ]; text_addr( txtaddr_l, &ph1->tunnel->saddr_l, true ); text_addr( txtaddr_r, &ph1->tunnel->saddr_r, true ); // // compare hash data // if( ph2->hash_r != hash_c ) { log.txt( LLOG_ERROR, "!! : phase2 sa rejected, responder quick mode hash invalid\n" "!! : %s <-> %s\n", txtaddr_l, txtaddr_r ); return LIBIKE_FAILED; } return LIBIKE_OK; } long _IKED::phase2_chk_hash_p( IDB_PH1 * ph1, IDB_PH2 * ph2 ) { // // generate hash data for comparison // BDATA hash_c; phase2_gen_hash_p( ph1, ph2, hash_c ); log.bin( LLOG_DEBUG, LLOG_DECODE, ph2->hash_r.buff(), ph2->hash_r.size(), "== : phase2 hash_p ( received )" ); // // build text strings for logging // char txtaddr_l[ LIBIKE_MAX_TEXTADDR ]; char txtaddr_r[ LIBIKE_MAX_TEXTADDR ]; text_addr( txtaddr_l, &ph1->tunnel->saddr_l, true ); text_addr( txtaddr_r, &ph1->tunnel->saddr_r, true ); // // compare hash data // if( ph2->hash_r != hash_c ) { log.txt( LLOG_ERROR, "!! : phase2 sa rejected, initiator liveliness proof hash invalid\n" "!! : %s <-> %s\n", txtaddr_l, txtaddr_r ); return LIBIKE_FAILED; } return LIBIKE_OK; } long _IKED::phase2_chk_params( IDB_PH1 * ph1, IDB_PH2 * ph2, PACKET_IKE & packet ) { // // are we initiator or responder // if( !ph2->initiator ) { // // configure responder ids // ph2->ph2id_ls = ph2->ph2id_rd; ph2->ph2id_ld = ph2->ph2id_rs; } // // generate address strings // char txtid_rs[ LIBIKE_MAX_TEXTP2ID ]; char txtid_rd[ LIBIKE_MAX_TEXTP2ID ]; char txtid_ls[ LIBIKE_MAX_TEXTP2ID ]; char txtid_ld[ LIBIKE_MAX_TEXTP2ID ]; text_ph2id( txtid_rs, &ph2->ph2id_rs ); text_ph2id( txtid_rd, &ph2->ph2id_rd ); text_ph2id( txtid_ls, &ph2->ph2id_ls ); text_ph2id( txtid_ld, &ph2->ph2id_ld ); // // are we initiator or responder // if( ph2->initiator ) { // // select an acceptable proposal // if( phase2_sel_prop( ph2 ) != LIBIKE_OK ) { packet.notify = ISAKMP_N_NO_PROPOSAL_CHOSEN; return LIBIKE_FAILED; } ph2->lstate |= LSTATE_CHKPROP; // // validate that the responders // ids match the initiator ids // if( !cmp_ph2id( ph2->ph2id_ls, ph2->ph2id_rd, true ) || !cmp_ph2id( ph2->ph2id_ld, ph2->ph2id_rs, true ) ) { log.txt( LLOG_ERROR, "ii : phase2 rejected, id value mismatch\n" "ii : - loc %s -> %s\n" "ii : - rmt %s -> %s\n", txtid_ls, txtid_ld, txtid_rs, txtid_rd ); packet.notify = ISAKMP_N_INVALID_ID_INFORMATION; return LIBIKE_FAILED; } // // locate outbound ipsec policy // IDB_POLICY * policy_out; if( !idb_list_policy.find( true, &policy_out, IPSEC_DIR_OUTBOUND, IPSEC_POLICY_IPSEC, NULL, &ph2->plcyid_out, NULL, NULL, NULL, NULL ) ) { log.txt( LLOG_ERROR, "ii : phase2 rejected, no matching outbound policy found\n" "ii : - loc %s -> %s\n" "ii : - rmt %s -> %s\n", txtid_ls, txtid_ld, txtid_rs, txtid_rd ); packet.notify = ISAKMP_N_INVALID_ID_INFORMATION; return LIBIKE_FAILED; } // // check all notification payloads // now to catch responder lifetime // notifications // if( ph2->notifications.count() ) { IKE_NOTIFY notify; long nindex = 0; while( ph2->notifications.get( notify, nindex++ ) ) inform_chk_notify( ph1, ¬ify, true ); } // // acquire spis from pfkey // pfkey_send_getspi( policy_out, ph2 ); // // cleanup // policy_out->dec( true ); } else { // // verify the initiators ids are // valid for a localy configured // security policy // IDB_POLICY * policy_in; IDB_POLICY * policy_out; IKE_PH2ID * ph2id_rs = &ph2->ph2id_rs; IKE_PH2ID * ph2id_rd = &ph2->ph2id_rd; // // if we are using the shared policy // level, we match the first policies // for the peer using the destination // id value only. The source id value // is irrelevant as it is generic. // if( ph2->tunnel->peer->plcy_level == POLICY_LEVEL_SHARED ) ph2id_rs = NULL; // // locate inbound ipsec policy // if( !idb_list_policy.find( true, &policy_in, IPSEC_DIR_INBOUND, IPSEC_POLICY_IPSEC, NULL, NULL, &ph2->tunnel->saddr_r, &ph2->tunnel->saddr_l, ph2id_rs, ph2id_rd ) ) { log.txt( LLOG_ERROR, "ii : phase2 rejected, no matching inbound policy found\n" "ii : - loc %s -> %s\n" "ii : - rmt %s -> %s\n", txtid_ls, txtid_ld, txtid_rs, txtid_rd ); packet.notify = ISAKMP_N_INVALID_ID_INFORMATION; return LIBIKE_FAILED; } ph2->plcyid_in = policy_in->sp.id; // // locate outbound ipsec policy // if( !idb_list_policy.find( true, &policy_out, IPSEC_DIR_OUTBOUND, IPSEC_POLICY_IPSEC, NULL, NULL, &ph2->tunnel->saddr_l, &ph2->tunnel->saddr_r, ph2id_rd, ph2id_rs ) ) { log.txt( LLOG_ERROR, "ii : phase2 rejected, no matching outbound policy found\n" "ii : - loc %s -> %s\n" "ii : - rmt %s -> %s\n", txtid_ls, txtid_ld, txtid_rs, txtid_rd ); policy_in->dec( true ); packet.notify = ISAKMP_N_INVALID_ID_INFORMATION; return LIBIKE_FAILED; } ph2->plcyid_out = policy_out->sp.id; // // compare the protocol parameters // if( !policy_cmp_prots( policy_in, policy_out ) ) { log.txt( LLOG_ERROR, "ii : phase2 rejected, inbound / outbound policy mismatch\n" "ii : - loc %s -> %s\n" "ii : - rmt %s -> %s\n", txtid_ls, txtid_ld, txtid_rs, txtid_rd ); policy_in->dec( true ); policy_out->dec( true ); packet.notify = ISAKMP_N_INVALID_ID_INFORMATION; return LIBIKE_FAILED; } // // configure the proposal list // phase2_gen_prop( ph2, policy_out ); // // configure the phase2 dh group // ph2->setup_dhgrp(); // // select an acceptable proposal // if( phase2_sel_prop( ph2 ) != LIBIKE_OK ) { policy_in->dec( true ); policy_out->dec( true ); packet.notify = ISAKMP_N_NO_PROPOSAL_CHOSEN; return LIBIKE_FAILED; } ph2->lstate |= LSTATE_CHKPROP; // // acquire spis from pfkey // pfkey_send_getspi( policy_in, ph2 ); pfkey_send_getspi( policy_out, ph2 ); // // cleanup // policy_in->dec( true ); policy_out->dec( true ); } // // ids accepted // log.txt( LLOG_INFO, "ii : phase2 ids accepted\n" "ii : - loc %s -> %s\n" "ii : - rmt %s -> %s\n", txtid_ls, txtid_ld, txtid_rs, txtid_rd ); return LIBIKE_OK; } long _IKED::phase2_gen_keys( IDB_PH1 * ph1, IDB_PH2 * ph2 ) { // // if pfs is being used, determine // our new shared secret now // BDATA shared; if( ph2->dhgr_id ) { if( level >= LLOG_DECODE ) { BDATA prv; prv.size( ph2->dh_size ); BN_bn2bin( ph2->dh->priv_key, prv.buff() ); log.bin( LLOG_DECODE, LLOG_DECODE, prv.buff(), prv.size(), "ii : computed PFS DH private key" ); log.bin( LLOG_DECODE, LLOG_DECODE, ph2->xl.buff(), ph2->xl.size(), "ii : computed PFS DH public key" ); log.bin( LLOG_DECODE, LLOG_DECODE, ph2->xr.buff(), ph2->xr.size(), "ii : received PFS DH public key" ); } // // validate the dh group size // if( ph2->xr.size() != ph2->dh_size ) { log.txt( LLOG_ERROR, "!! : PFS DH group size mismatch ( %d != %d )\n", ph2->xr.size(), ph2->dh_size ); ph2->status( XCH_STATUS_DEAD, XCH_FAILED_MSG_FORMAT, 0 ); return LIBIKE_FAILED; } // // determine shared secret // BIGNUM * gx = BN_new(); BN_bin2bn( ph2->xr.buff(), ph2->dh_size, gx ); shared.size( ph2->dh_size ); long result = DH_compute_key( shared.buff(), gx, ph2->dh ); BN_free( gx ); if( result < 0 ) { log.txt( LLOG_ERROR, "!! : failed to compute PFS DH shared secret\n" ); ph2->status( XCH_STATUS_DEAD, XCH_FAILED_MSG_CRYPTO, 0 ); return LIBIKE_FAILED; } // // fixup shared secret buffer alignment // if( ph2->dh_size > result ) { shared.size( result ); shared.ins( 0, ph2->dh_size - result ); } log.bin( LLOG_DEBUG, LLOG_DECODE, shared.buff(), shared.size(), "== : PFS DH shared secret" ); } // // step through our negotiated // proposal transform list // long lifetime = 0; long pindex = 0; while( true ) { IKE_PROPOSAL * proposal_l; IKE_PROPOSAL * proposal_r; if( !ph2->plist_l.get( &proposal_l, pindex ) || !ph2->plist_r.get( &proposal_r, pindex ) ) break; lifetime = proposal_l->life_sec; proposal_r->life_sec = lifetime; phase2_gen_keys( ph1, ph2, IPSEC_DIR_INBOUND, proposal_l, shared ); phase2_gen_keys( ph1, ph2, IPSEC_DIR_OUTBOUND, proposal_r, shared ); pindex++; } // // set the initialization time // and life time seconds // ph2->inc( true ); ph2->inc( true ); ph2->event_hard.delay = lifetime + 1; ph2->event_soft.delay = lifetime + 1; ph2->event_soft.delay *= PFKEY_SOFT_LIFETIME_RATE; ph2->event_soft.delay /= 100; ph2->event_soft.diff = ph2->event_hard.delay - ph2->event_soft.delay; ph2->event_hard.delay *= 1000; ith_timer.add( &ph2->event_hard ); ph2->event_soft.delay *= 1000; ith_timer.add( &ph2->event_soft ); ph1->tunnel->stats.sa_good++; return LIBIKE_OK; } #define PH2_MAX_KEYLEN ( ( EVP_MAX_KEY_LENGTH + HMAC_MAX_MD_CBLOCK ) * 2 ) long _IKED::phase2_gen_keys( IDB_PH1 * ph1, IDB_PH2 * ph2, long dir, IKE_PROPOSAL * proposal, BDATA & shared ) { // // determine encryption key size // long key_size_c = 0; if( proposal->proto == ISAKMP_PROTO_IPSEC_ESP ) { if( proposal->ciph_kl ) { // // variable key size // key_size_c = ( proposal->ciph_kl + 7 ) / 8; } else { // // fixed or default key size // switch( proposal->xform ) { case ISAKMP_ESP_DES: key_size_c = EVP_CIPHER_key_length( EVP_des_cbc() ); break; case ISAKMP_ESP_BLOWFISH: key_size_c = EVP_CIPHER_key_length( EVP_bf_cbc() ); break; case ISAKMP_ESP_3DES: key_size_c = EVP_CIPHER_key_length( EVP_des_ede3_cbc() ); break; case ISAKMP_ESP_CAST: key_size_c = EVP_CIPHER_key_length( EVP_cast5_cbc() ); break; case ISAKMP_ESP_AES: key_size_c = EVP_CIPHER_key_length( EVP_aes_128_cbc() ); break; } } } // // determine authentication key size // long key_size_h = 0; if( ( proposal->proto == ISAKMP_PROTO_IPSEC_AH ) || ( proposal->proto == ISAKMP_PROTO_IPSEC_ESP ) ) { switch( proposal->hash_id ) { case ISAKMP_AUTH_HMAC_MD5: key_size_h = EVP_MD_size( EVP_md5() ); break; case ISAKMP_AUTH_HMAC_SHA1: key_size_h = EVP_MD_size( EVP_sha1() ); break; case ISAKMP_AUTH_HMAC_SHA2_256: key_size_h = EVP_MD_size( EVP_sha256() ); break; case ISAKMP_AUTH_HMAC_SHA2_384: key_size_h = EVP_MD_size( EVP_sha384() ); break; case ISAKMP_AUTH_HMAC_SHA2_512: key_size_h = EVP_MD_size( EVP_sha512() ); break; } } // // do this twice, once for the inbound // sa and once for the outbound sa // unsigned char key_data[ PH2_MAX_KEYLEN ]; long key_size = key_size_c + key_size_h; long skeyid_size = ph1->hash_size; // // grow our key to be a multiple // of SKEYID_d ( HMAC block size ) if( key_size % skeyid_size ) key_size += skeyid_size - ( key_size % skeyid_size ); assert( key_size < PH2_MAX_KEYLEN ); // // create our extended key material // // KEYMAT = K1 | K2 | K3 | ... // // K1 = prf( SKEYID_d, [ g(qm)^xy | ] protocol | SPI | Ni_b | Nr_b ) // K2 = prf( SKEYID_d, K1 | [ g(qm)^xy | ] protocol | SPI | Ni_b | Nr_b ) // K3 = prf( SKEYID_d, K2 | [ g(qm)^xy | ] protocol | SPI | Ni_b | Nr_b ) // HMAC_CTX ctx_prf; HMAC_CTX_init( &ctx_prf ); HMAC_Init_ex( &ctx_prf, ph1->skeyid_d.buff(), ( int ) ph1->skeyid_d.size(), ph1->evp_hash, NULL ); if( ph2->dhgr_id ) HMAC_Update( &ctx_prf, shared.buff(), shared.size() ); HMAC_Update( &ctx_prf, ( unsigned char * ) &proposal->proto, 1 ); HMAC_Update( &ctx_prf, ( unsigned char * ) &proposal->spi, 4 ); if( ph2->initiator ) { HMAC_Update( &ctx_prf, ph2->nonce_l.buff(), ph2->nonce_l.size() ); HMAC_Update( &ctx_prf, ph2->nonce_r.buff(), ph2->nonce_r.size() ); } else { HMAC_Update( &ctx_prf, ph2->nonce_r.buff(), ph2->nonce_r.size() ); HMAC_Update( &ctx_prf, ph2->nonce_l.buff(), ph2->nonce_l.size() ); } HMAC_Final( &ctx_prf, key_data, NULL ); for( long size = skeyid_size; size < key_size; size += skeyid_size ) { HMAC_Init_ex( &ctx_prf, ph1->skeyid_d.buff(), ( int ) ph1->skeyid_d.size(), ph1->evp_hash, NULL ); HMAC_Update( &ctx_prf, key_data + size - skeyid_size, skeyid_size ); if( ph2->dhgr_id ) HMAC_Update( &ctx_prf, shared.buff(), shared.size() ); HMAC_Update( &ctx_prf, ( unsigned char * ) &proposal->proto, 1 ); HMAC_Update( &ctx_prf, ( unsigned char * ) &proposal->spi, 4 ); if( ph2->initiator ) { HMAC_Update( &ctx_prf, ph2->nonce_l.buff(), ph2->nonce_l.size() ); HMAC_Update( &ctx_prf, ph2->nonce_r.buff(), ph2->nonce_r.size() ); } else { HMAC_Update( &ctx_prf, ph2->nonce_r.buff(), ph2->nonce_r.size() ); HMAC_Update( &ctx_prf, ph2->nonce_l.buff(), ph2->nonce_l.size() ); } HMAC_Final( &ctx_prf, key_data + size, 0 ); } HMAC_CTX_cleanup( &ctx_prf ); // // separate encrypt and auth key data // BDATA ekey; BDATA akey; if( key_size_c ) { ekey.set( key_data, key_size_c ); log.bin( LLOG_DEBUG, LLOG_DECODE, ekey.buff(), ekey.size(), "== : spi cipher key data" ); } if( key_size_h ) { akey.set( key_data + key_size_c, key_size_h ); log.bin( LLOG_DEBUG, LLOG_DECODE, akey.buff(), akey.size(), "== : spi hmac key data" ); } // // send our sa add/update to pfkey // pfkey_send_update( ph2, proposal, ekey, akey, dir ); ph2->lstate |= LSTATE_HASKEYS; return LIBIKE_OK; } ike-2.2.1+dfsg/source/iked/ike.h000066400000000000000000000505601223036517100163460ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #ifndef _IKE_H_ #define _IKE_H_ #include "libidb.h" #include "inttypes.h" #define CONF_STRLEN 256 // // IPSEC DOI - RFC 2407 // // ipsec situations #define ISAKMP_SIT_IDENT_ONLY 0x1 // identity only #define ISAKMP_SIT_SECRECY 0x2 // labled secrecy #define ISAKMP_SIT_INTEGRITY 0x4 // labled integrity // ipsec security protocols #define ISAKMP_PROTO_ISAKMP 1 #define ISAKMP_PROTO_IPSEC_AH 2 #define ISAKMP_PROTO_IPSEC_ESP 3 #define ISAKMP_PROTO_IPCOMP 4 // ipsec isakmp transforms #define ISAKMP_KEY_IKE 1 // ipsec ah transforms #define ISAKMP_AH_MD5 2 #define ISAKMP_AH_SHA 3 #define ISAKMP_AH_DES 4 #define ISAKMP_AH_SHA256 5 #define ISAKMP_AH_SHA384 6 #define ISAKMP_AH_SHA512 7 // ipsec esp transforms #define ISAKMP_ESP_DES_IV64 1 #define ISAKMP_ESP_DES 2 #define ISAKMP_ESP_3DES 3 #define ISAKMP_ESP_RC5 4 #define ISAKMP_ESP_IDEA 5 #define ISAKMP_ESP_CAST 6 #define ISAKMP_ESP_BLOWFISH 7 #define ISAKMP_ESP_3IDEA 8 #define ISAKMP_ESP_DES_IV32 9 #define ISAKMP_ESP_RC4 10 #define ISAKMP_ESP_NULL 11 #define ISAKMP_ESP_AES 12 // ipsec ipcomp transforms #define ISAKMP_IPCOMP_NONE 0 #define ISAKMP_IPCOMP_OUI 1 #define ISAKMP_IPCOMP_DEFLATE 2 #define ISAKMP_IPCOMP_LZS 3 // ipsec sa attributes #define ISAKMP_ATTR_LIFE_TYPE 1 // basic #define ISAKMP_ATTR_LIFE_DURATION 2 // variable #define ISAKMP_ATTR_GROUP_DESC 3 // basic #define ISAKMP_ATTR_ENCAP_MODE 4 // basic #define ISAKMP_ATTR_AUTH_ALGORITHM 5 // basic #define ISAKMP_ATTR_KEY_LEGTH 6 // basic #define ISAKMP_ATTR_KEY_ROUNDS 7 // basic #define ISAKMP_ATTR_CMPR_DICT_SIZE 8 // basic #define ISAKMP_ATTR_CMPR_ALGORITHM 9 // variable // life type values #define ISAKMP_LIFETYPE_SECONDS 1 #define ISAKMP_LIFETYPE_KBYTES 2 // encapsulation mode values #define ISAKMP_ENCAP_TUNNEL 1 #define ISAKMP_ENCAP_TRANSPORT 2 #define ISAKMP_ENCAP_RFC_UDP_TUNNEL 3 #define ISAKMP_ENCAP_RFC_UDP_TRANSPORT 4 #define ISAKMP_ENCAP_VXX_UDP_TUNNEL 61443 #define ISAKMP_ENCAP_VXX_UDP_TRANSPORT 61444 // authentication algorithm values #define ISAKMP_AUTH_HMAC_MD5 1 #define ISAKMP_AUTH_HMAC_SHA1 2 #define ISAKMP_AUTH_DES_MAC 3 #define ISAKMP_AUTH_KPDK 4 #define ISAKMP_AUTH_HMAC_SHA2_256 5 #define ISAKMP_AUTH_HMAC_SHA2_384 6 #define ISAKMP_AUTH_HMAC_SHA2_512 7 // identification types #define ISAKMP_ID_NONE 0 #define ISAKMP_ID_IPV4_ADDR 1 #define ISAKMP_ID_FQDN 2 #define ISAKMP_ID_USER_FQDN 3 #define ISAKMP_ID_IPV4_ADDR_SUBNET 4 #define ISAKMP_ID_IPV6_ADDR 5 #define ISAKMP_ID_IPV6_ADDR_SUBNET 6 #define ISAKMP_ID_IPV4_ADDR_RANGE 7 #define ISAKMP_ID_IPV6_ADDR_RANGE 8 #define ISAKMP_ID_ASN1_DN 9 #define ISAKMP_ID_ASN1_GN 10 #define ISAKMP_ID_KEY_ID 11 // // ISAKMP - RFC 2408 // // version 1.0 values #define ISAKMP_MAJOR 1 #define ISAKMP_MINOR 0 #define ISAKMP_VERSION ISAKMP_MAJOR << 4 | ISAKMP_MINOR // payload types #define ISAKMP_PAYLOAD_NONE 0 // no more payloads #define ISAKMP_PAYLOAD_SA 1 // security association #define ISAKMP_PAYLOAD_PROPOSAL 2 // proposal #define ISAKMP_PAYLOAD_TRANSFORM 3 // transform #define ISAKMP_PAYLOAD_KEX 4 // key exchange #define ISAKMP_PAYLOAD_IDENT 5 // identificaion #define ISAKMP_PAYLOAD_CERT 6 // certificate #define ISAKMP_PAYLOAD_CERT_REQ 7 // certificate request #define ISAKMP_PAYLOAD_HASH 8 // hash #define ISAKMP_PAYLOAD_SIGNATURE 9 // signature #define ISAKMP_PAYLOAD_NONCE 10 // noonce #define ISAKMP_PAYLOAD_NOTIFY 11 // notification #define ISAKMP_PAYLOAD_DELETE 12 // delete #define ISAKMP_PAYLOAD_VEND 13 // vendor id #define ISAKMP_PAYLOAD_ATTRIB 14 // mode config attibutes #define ISAKMP_PAYLOAD_NAT_RFC_DISC 20 // nat discovery #define ISAKMP_PAYLOAD_NAT_RFC_ORIG 21 // nat original address #define ISAKMP_PAYLOAD_NAT_VXX_DISC 130 // nat discovery #define ISAKMP_PAYLOAD_NAT_VXX_ORIG 131 // nat original address #define ISAKMP_PAYLOAD_FRAGMENT 132 // fragmentation payload // exchange types #define ISAKMP_EXCH_BASE 1 // base #define ISAKMP_EXCH_IDENT_PROTECT 2 // identity protection ( main ) #define ISAKMP_EXCH_AUTHENTICATION 3 // authentication only #define ISAKMP_EXCH_AGGRESSIVE 4 // aggressive mode #define ISAKMP_EXCH_INFORMATIONAL 5 // informational #define ISAKMP_EXCH_CONFIG 6 // isakmp config // certificate types #define ISAKMP_CERT_NONE 0 #define ISAKMP_CERT_PKCS7 1 #define ISAKMP_CERT_PGP 2 #define ISAKMP_CERT_DNS_SIGNED 3 #define ISAKMP_CERT_X509_SIG 4 #define ISAKMP_CERT_X509_KEX 5 #define ISAKMP_CERT_KERBEROS 6 #define ISAKMP_CERT_CRL 7 #define ISAKMP_CERT_ARL 8 #define ISAKMP_CERT_SPKI 9 #define ISAKMP_CERT_X509_ATTR 10 #define ISAKMP_CERT_RSA_PLAIN 11 // isakmp doi types #define ISAKMP_DOI_GENERIC 0 #define ISAKMP_DOI_IPSEC 1 // isakmp flags #define ISAKMP_FLAGS_OFFSET 19 #define ISAKMP_FLAG_ENCRYPT 0x01 // payload is encrypted #define ISAKMP_FLAG_COMMIT 0x02 // synchronous exchange #define ISAKMP_FLAG_AUTH_ONLY 0x04 // authentication only // notify types #define ISAKMP_N_INVALID_PAYLOAD_TYPE 1 #define ISAKMP_N_DOI_NOT_SUPPORTED 2 #define ISAKMP_N_SITUATION_NOT_SUPPORTED 3 #define ISAKMP_N_INVALID_COOKIE 4 #define ISAKMP_N_INVALID_MAJOR_VERSION 5 #define ISAKMP_N_INVALID_MINOR_VERSION 6 #define ISAKMP_N_INVALID_EXCHANGE_TYPE 7 #define ISAKMP_N_INVALID_FLAGS 8 #define ISAKMP_N_INVALID_MESSAGE_ID 9 #define ISAKMP_N_INVALID_PROTOCOL_ID 10 #define ISAKMP_N_INVALID_SPI 11 #define ISAKMP_N_INVALID_TRANSFORM_ID 12 #define ISAKMP_N_ATTRIBUTES_NOT_SUPPORTED 13 #define ISAKMP_N_NO_PROPOSAL_CHOSEN 14 #define ISAKMP_N_BAD_PROPOSAL_SYNTAX 15 #define ISAKMP_N_PAYLOAD_MALFORMED 16 #define ISAKMP_N_INVALID_KEY_INFORMATION 17 #define ISAKMP_N_INVALID_ID_INFORMATION 18 #define ISAKMP_N_INVALID_CERT_ENCODING 19 #define ISAKMP_N_INVALID_CERTIFICATE 20 #define ISAKMP_N_CERT_TYPE_UNSUPPORTED 21 #define ISAKMP_N_INVALID_CERT_AUTHORITY 22 #define ISAKMP_N_INVALID_HASH_INFORMATION 23 #define ISAKMP_N_AUTHENTICATION_FAILED 24 #define ISAKMP_N_INVALID_SIGNATURE 25 #define ISAKMP_N_ADDRESS_NOTIFICATION 26 #define ISAKMP_N_NOTIFY_SA_LIFETIME 27 #define ISAKMP_N_CERTIFICATE_UNAVAILABLE 28 #define ISAKMP_N_UNSUPPORTED_EXCHANGE_TYPE 29 #define ISAKMP_N_UNEQUAL_PAYLOAD_LENGTHS 30 // // IKE - RFC 2409 // // echange types #define ISAKMP_EXCH_QUICK 32 // quick #define ISAKMP_EXCH_NEW_GROUP 33 // new group // notification types #define ISAKMP_N_RESPONDER_LIFETIME 24576 #define ISAKMP_N_REPLAY_STATUS 24577 #define ISAKMP_N_INITIAL_CONTACT 24578 // // attribute types // #define BASIC 0x8000 #define IKE_ATTR_TRANSFORM 1 // basic #define IKE_ATTR_HASH 2 // basic #define IKE_ATTR_AUTH_METHOD 3 // basic #define IKE_ATTR_GROUP_DESC 4 // basic #define IKE_ATTR_GROUP_TYPE 5 // basic #define IKE_ATTR_GROUP_PRIME 6 // variable #define IKE_ATTR_GROUP_GENERATOR_1 7 // variable #define IKE_ATTR_GROUP_GENERATOR_2 8 // variable #define IKE_ATTR_GROUP_CURVE_A 9 // variable #define IKE_ATTR_GROUP_CURVE_B 10 // variable #define IKE_ATTR_LIFE_TYPE 11 // basic #define IKE_ATTR_LIFE_DURATION 12 // variable #define IKE_ATTR_PRF 13 // basic #define IKE_ATTR_KEY_LENGTH 14 // basic #define IKE_ATTR_FIELD_SIZE 15 // basic #define IKE_ATTR_GROUP_ORDER 16 // variable #define IKE_CIPHER_DES 1 #define IKE_CIPHER_IDEA 2 #define IKE_CIPHER_BLOWFISH 3 #define IKE_CIPHER_RC5_R16_B64 4 #define IKE_CIPHER_3DES 5 #define IKE_CIPHER_CAST 6 #define IKE_CIPHER_AES 7 #define IKE_HASH_MD5 1 #define IKE_HASH_SHA1 2 #define IKE_HASH_TIGER 3 #define IKE_HASH_SHA2_256 4 #define IKE_HASH_SHA2_384 5 #define IKE_HASH_SHA2_512 6 #define IKE_AUTH_PRESHARED_KEY 1 #define IKE_AUTH_SIG_DSA 2 #define IKE_AUTH_SIG_RSA 3 #define IKE_AUTH_SIG_RSA_ENCRYPT 4 #define IKE_AUTH_SIG_RSA_REVISED 5 #define IKE_GRP_GROUP1 1 // oakley modp 768 #define IKE_GRP_GROUP2 2 // oakley modp 1024 #define IKE_GRP_GROUP3 3 // oakley ecn 155 #define IKE_GRP_GROUP4 4 // oakley ecn 185 #define IKE_GRP_GROUP5 5 // oakley modp 1536 #define IKE_GRP_GROUP14 14 // oakley modp 2048 #define IKE_GRP_GROUP15 15 // oakley modp 3072 #define IKE_GRP_GROUP16 16 // oakley modp 4096 #define IKE_GRP_GROUP17 17 // oakley modp 6144 #define IKE_GRP_GROUP18 18 // oakley modp 8192 #define IKE_GRP_TYPE_MODP 1 #define IKE_GRP_TYPE_ECP 2 #define IKE_GRP_TYPE_EC2N 3 #define IKE_LIFE_TYPE_SECONDS 1 #define IKE_LIFE_TYPE_KBYTES 2 // // IKE protocol extensions // // ike fragmentation #define IKE_FRAG_FLAG_LAST 0x01 // cisco high availability #define ISAKMP_N_UNITY_LOAD_BALANCE 40501 #define ISAKMP_N_UNITY_GROUP_HASH 40503 // dead peer detection #define ISAKMP_N_DPD_R_U_THERE 36136 #define ISAKMP_N_DPD_R_U_THERE_ACK 36137 // configuration exchange types #define ISAKMP_CFG_REQUEST 1 #define ISAKMP_CFG_REPLY 2 #define ISAKMP_CFG_SET 3 #define ISAKMP_CFG_ACK 4 // configuration attributes #define INTERNAL_IP4_ADDRESS 1 // variable 0 or 4 octets #define INTERNAL_IP4_NETMASK 2 // variable 0 or 4 octets #define INTERNAL_IP4_DNS 3 // variable 0 or 4 octets #define INTERNAL_IP4_NBNS 4 // variable 0 or 4 octets #define INTERNAL_ADDRESS_EXPIRY 5 // variable 0 or 4 octets #define INTERNAL_IP4_DHCP 6 // variable 0 or 4 octets #define APPLICATION_VERSION 7 // variable 0 or more #define INTERNAL_IP6_ADDRESS 8 // variable 0 or 16 octets #define INTERNAL_IP6_NETMASK 9 // variable 0 or 16 octets #define INTERNAL_IP6_DNS 10 // variable 0 or 16 octets #define INTERNAL_IP6_NBNS 11 // variable 0 or 16 octets #define INTERNAL_IP6_DHCP 12 // variable 0 or 16 octets #define INTERNAL_IP4_SUBNET 13 // variable 0 or 8 octets #define SUPPORTED_ATTRIBUTES 14 // variable 0 or multiples of 2 #define INTERNAL_IP6_SUBNET 15 // variable 0 or 17 octets // extended authentication modes #define XAUTH_AUTH_INIT_PSK 65001 #define XAUTH_AUTH_RESP_PSK 65002 #define XAUTH_AUTH_INIT_DSS 65003 #define XAUTH_AUTH_RESP_DSS 65004 #define XAUTH_AUTH_INIT_RSA 65005 #define XAUTH_AUTH_RESP_RSA 65006 #define XAUTH_AUTH_INIT_RSA_ENC 65007 #define XAUTH_AUTH_RESP_RSA_ENC 65008 #define XAUTH_AUTH_INIT_RSA_REV 65009 #define XAUTH_AUTH_RESP_RSA_REV 65010 // hybrid authentication modes #define HYBRID_AUTH_INIT_RSA 64221 #define HYBRID_AUTH_RESP_RSA 64222 #define HYBRID_AUTH_INIT_DSS 64223 #define HYBRID_AUTH_RESP_DSS 64224 // extended authentication types #define XAUTH_TYPE_GENERIC 0 #define XAUTH_TYPE_RADIUS_CHAP 1 #define XAUTH_TYPE_OTP 2 #define XAUTH_TYPE_SKEY 3 // extended authentication attributes #define XAUTH_TYPE 16520 // basic #define XAUTH_USER_NAME 16521 // variable #define XAUTH_USER_PASSWORD 16522 // variable #define XAUTH_PASSCODE 16523 // variable #define XAUTH_MESSAGE 16524 // variable #define XAUTH_CHALLENGE 16525 // variable #define XAUTH_DOMAIN 16526 // variable #define XAUTH_STATUS 16527 // basic #define XAUTH_NEXT_PIN 16528 // variable #define XAUTH_ANSWER 16529 // variable // unity configuration attributes #ifdef WIN32 #define UNITY_APP_VERSION_STRING "Cisco Systems VPN Client 4.8.01.0300:WinNT" #else #define UNITY_APP_VERSION_STRING "Cisco Systems VPN Client 4.8.01 (0640):Linux" #endif #define UNITY_BANNER 28672 // variable #define UNITY_SAVE_PASSWD 28673 // basic #define UNITY_DEF_DOMAIN 28674 // variable #define UNITY_SPLIT_DOMAIN 28675 // variable #define UNITY_SPLIT_INCLUDE 28676 // variable #define UNITY_NATT_PORT 28677 // basic #define UNITY_SPLIT_EXCLUDE 28678 // variable #define UNITY_PFS 28679 // basic #define UNITY_FW_TYPE 28680 // variable #define UNITY_BACKUP_SERVERS 28681 // variable #define UNITY_DDNS_HOSTNAME 28682 // variable // checkpoint extended authentication attributes #define CHKPT_TYPE 13 #define CHKPT_USER_NAME 14 #define CHKPT_USER_PASSWORD 15 #define CHKPT_MESSAGE 17 #define CHKPT_CHALLENGE 18 #define CHKPT_STATUS 20 // checkpoint configuration attributes #define CHKPT_DEF_DOMAIN 16387 #define CHKPT_MAC_ADDRESS 16388 #define CHKPT_MARCIPAN_REASON_CODE 16389 #define CHKPT_UNKNOWN1 16400 #define CHKPT_UNKNOWN2 16401 #define CHKPT_UNKNOWN3 16402 // // implementation specific constants // #define ISAKMP_COOKIE_SIZE 8 #define ISAKMP_SPI_SIZE 4 #define ISAKMP_CPI_SIZE 2 #define ISAKMP_NONCE_SIZE 20 #define ISAKMP_NONCE_MIN 4 #define ISAKMP_NONCE_MAX 252 #define ISAKMP_CERT_MAX ( 1024 * 32 ) #define ISAKMP_CREQ_MAX ( 1024 * 4 ) #define ISAKMP_SIGN_MAX ( 1024 * 4 ) // // ipsec config constants // #define IPSEC_CONTACT_SERVER 1 #define IPSEC_CONTACT_CLIENT 2 #define IPSEC_CONTACT_INIT 3 #define IPSEC_CONTACT_RESP 4 #define IPSEC_CONTACT_BOTH 5 #define IPSEC_NATT_DISABLE 0 #define IPSEC_NATT_ENABLE 1 #define IPSEC_NATT_FORCE_DRAFT 2 #define IPSEC_NATT_FORCE_RFC 3 #define IPSEC_NATT_FORCE_CISCO 4 #define IPSEC_FRAG_DISABLE 0 #define IPSEC_FRAG_ENABLE 1 #define IPSEC_FRAG_FORCE 2 #define IPSEC_DPD_DISABLE 0 #define IPSEC_DPD_ENABLE 1 #define IPSEC_DPD_FORCE 2 #define IPSEC_NATT_NONE 0 #define IPSEC_NATT_CISCO 1 #define IPSEC_NATT_V00 2 #define IPSEC_NATT_V01 3 #define IPSEC_NATT_V02 4 #define IPSEC_NATT_V03 5 #define IPSEC_NATT_RFC 255 #define IPSEC_OPTS_SPLITNET 0x0001 #define IPSEC_OPTS_BANNER 0x0002 #define IPSEC_OPTS_PFS 0x0004 #define IPSEC_OPTS_ADDR 0x0008 #define IPSEC_OPTS_MASK 0x0010 #define IPSEC_OPTS_NBNS 0x0020 #define IPSEC_OPTS_DNSS 0x0040 #define IPSEC_OPTS_DOMAIN 0x0080 #define IPSEC_OPTS_SPLITDNS 0x0100 #define IPSEC_OPTS_SAVEPW 0x0200 #define IPSEC_OPTS_CISCO_UDP 0x0400 #define IPSEC_OPTS_CISCO_GRP 0x0800 #define IPSEC_OPTS_VEND_CHKPT 0x1000 #define IPSEC_DNSS_MAX 8 #define IPSEC_NBNS_MAX 4 #define CONFIG_MODE_NONE 0 #define CONFIG_MODE_PULL 1 #define CONFIG_MODE_PUSH 2 #define CONFIG_MODE_DHCP 3 #define POLICY_MODE_DISABLE 0 #define POLICY_MODE_COMPAT 1 #define POLICY_MODE_CONFIG 2 #define POLICY_LEVEL_AUTO 0 #define POLICY_LEVEL_USE 1 #define POLICY_LEVEL_REQUIRE 2 #define POLICY_LEVEL_UNIQUE 3 #define POLICY_LEVEL_SHARED 4 // // IKE structures and classes // typedef struct _IKE_SADDR { union { sockaddr saddr; sockaddr_in saddr4; }; }IKE_SADDR; typedef struct _IKE_ATTR : public IDB_ENTRY { bool basic; uint16_t atype; uint16_t bdata; BDATA vdata; }IKE_ATTR; typedef struct _IKE_COOKIES { unsigned char i[ ISAKMP_COOKIE_SIZE ]; unsigned char r[ ISAKMP_COOKIE_SIZE ]; }IKE_COOKIES; typedef struct _IKE_PH1ID { uint8_t type; in_addr addr; BDATA varid; }IKE_PH1ID; typedef struct _IKE_PH2ID { uint8_t prot; uint16_t port; uint8_t type; in_addr addr1; in_addr addr2; }IKE_PH2ID; typedef struct _IKE_SPI { union { IKE_COOKIES cookies; // isakmp cookies uint32_t spi; // esp/ah spi uint16_t cpi; // ipcomp cpi }; uint8_t size; }IKE_SPI; typedef struct _IKE_PROPOSAL { uint8_t pnumb; uint8_t tnumb; uint8_t proto; uint8_t xform; uint16_t encap; uint16_t reqid; IKE_SPI spi; uint16_t ciph_id; uint16_t ciph_kl; uint16_t hash_id; uint16_t dhgr_id; uint16_t auth_id; uint32_t life_sec; uint32_t life_kbs; }IKE_PROPOSAL; typedef struct _IKE_PEER { IKE_SADDR saddr; unsigned char contact; unsigned char exchange; bool notify; bool nailed; long natt_mode; unsigned short natt_port; long natt_rate; long frag_ike_mode; size_t frag_ike_size; long frag_esp_mode; size_t frag_esp_size; long dpd_mode; long dpd_delay; long dpd_retry; long life_check; unsigned char idtype_l; unsigned char idtype_r; long plcy_mode; long plcy_level; long xconf_mode; }IKE_PEER; typedef struct _IKE_XAUTH { uint16_t type; BDATA user; BDATA pass; BDATA hash; BDATA context; }IKE_XAUTH; typedef struct _IKE_NSCFG { bool dnss_from_dhcp; // dns server list obtained from dhcp in_addr dnss_list[ IPSEC_DNSS_MAX ]; // dns server list uint32_t dnss_count; // dns server count uint32_t dnss_nodyn; // dns dynamic update disabled char dnss_suffix[ CONF_STRLEN ]; in_addr nbns_list[ IPSEC_NBNS_MAX ]; // wins server list uint32_t nbns_count; // wins server count uint32_t nbns_nopts; // wins options uint32_t nbns_ntype; // wins node type }IKE_NSCFG; typedef struct _IKE_XCONF { long opts; // enabled options long rqst; // request options in_addr addr; // network address in_addr mask; // network mask in_addr dhcp; // dhcp servers uint32_t expi; // address expires uint32_t vmtu; // adapter mtu uint16_t dhgr; // pfs dh group uint16_t svpw; // save password IKE_NSCFG nscfg; // name service config }IKE_XCONF; typedef struct _IKE_NOTIFY { uint8_t type; uint32_t doi; uint8_t proto; uint16_t code; IKE_SPI spi; BDATA data; }IKE_NOTIFY; typedef struct _IKE_FRAG : public IDB_ENTRY { public: long index; bool last; BDATA data; }IKE_FRAG; #pragma pack( 1 ) typedef struct _IKE_SUBNET { in_addr addr; in_addr mask; }IKE_SUBNET; typedef struct _IKE_UNITY_NET { in_addr addr; in_addr mask; uint8_t prot; uint8_t pad; uint16_t port_loc; uint16_t port_rmt; }IKE_UNITY_NET; #pragma pack() // // XXX : these need to move back // into iked.h // #pragma pack( 1 ) typedef struct _IKE_HEADER { IKE_COOKIES cookies; uint8_t payload; // initial payload uint8_t version; // isakmp version uint8_t exchange; // exchange type uint8_t flags; // flags uint32_t msgid; // message id uint32_t length; // message length }IKE_HEADER; typedef struct _IKE_PAYLOAD { uint8_t next; // next payload uint8_t reserved; // reserved uint16_t length; // payload size }IKE_PAYLOAD; #pragma pack() typedef struct _PLD_DATA { size_t oset; size_t size; }PLD_DATA; #endif ike-2.2.1+dfsg/source/iked/ike.idb.config.cpp000066400000000000000000000140011223036517100206700ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "iked.h" //============================================================================== // ike configuration exchange handle list //============================================================================== IDB_CFG * _IDB_LIST_CFG::get( int index ) { return static_cast( get_entry( index ) ); } bool _IDB_LIST_CFG::find( bool lock, IDB_CFG ** cfg, IDB_PH1 * ph1 ) { if( cfg != NULL ) *cfg = NULL; if( lock ) iked.lock_idb.lock(); // // step through our list of configs // and see if they match the msgid // long index = 0; for( ; index < count(); index++ ) { // // get the next config in our list // IDB_CFG * tmp_cfg = get( index ); // // match the phase1 id // if( tmp_cfg->ph1ref != ph1 ) continue; iked.log.txt( LLOG_DEBUG, "DB : config found\n" ); // // increase our refrence count // if( cfg != NULL ) { tmp_cfg->inc( false ); *cfg = tmp_cfg; } if( lock ) iked.lock_idb.unlock(); return true; } iked.log.txt( LLOG_DEBUG, "DB : config not found\n" ); if( lock ) iked.lock_idb.unlock(); return false; } //============================================================================== // ike configuration exchange handle list entry //============================================================================== _IDB_CFG::_IDB_CFG( IDB_PH1 * set_ph1ref, bool set_initiator ) { mtype = 0; ident = 0; ph1ref = set_ph1ref; // never accessed directly tunnel = set_ph1ref->tunnel; tunnel->inc( true ); initiator = set_initiator; // // skip xauth if disabled // if( !set_ph1ref->vendopts_l.flag.xauth ) xstate |= CSTATE_SENT_XRSLT | CSTATE_RECV_XRSLT; // // skip configuration if already negotiated // using pull mode or if the mode is set to // none ( manual ) // if( tunnel->peer->xconf_mode == CONFIG_MODE_PULL ) if( tunnel->tstate & TSTATE_VNET_CONFIG ) xstate |= CSTATE_SENT_XCONF | CSTATE_RECV_XCONF; if( ( tunnel->peer->xconf_mode == CONFIG_MODE_DHCP ) || ( tunnel->peer->xconf_mode == CONFIG_MODE_NONE ) ) xstate |= CSTATE_SENT_XCONF | CSTATE_RECV_XCONF; } _IDB_CFG::~_IDB_CFG() { clean(); // // dereference tunnel // tunnel->dec( false ); } //------------------------------------------------------------------------------ // abstract functions from parent class // const char * _IDB_CFG::name() { static const char * xname = "config"; return xname; } IKED_RC_LIST * _IDB_CFG::list() { return &iked.idb_list_cfg; } void _IDB_CFG::beg() { } void _IDB_CFG::end() { // // clear the resend queue // resend_clear( false, true ); } //------------------------------------------------------------------------------ // additional functions // bool _IDB_CFG::attr_add_b( unsigned short atype, unsigned short bdata ) { IKE_ATTR * attr = new IKE_ATTR; if( attr == NULL ) return false; attr->atype = atype; attr->basic = true; attr->bdata = bdata; return attrs.add_entry( attr ); } bool _IDB_CFG::attr_add_v( unsigned short atype, const void * vdata, size_t vsize ) { IKE_ATTR * attr = new IKE_ATTR; if( attr == NULL ) return false; attr->atype = atype; attr->basic = false; attr->vdata.set( ( char * ) vdata, vsize ); return attrs.add_entry( attr ); } bool _IDB_CFG::attr_has( unsigned short atype ) { long index = 0; long count = attr_count(); for( ; index < count; index++ ) { IKE_ATTR * attr = attr_get( index ); if( attr->atype == atype ) return true; } return false; } IKE_ATTR * _IDB_CFG::attr_get( long index ) { return static_cast( attrs.get_entry( index ) ); } long _IDB_CFG::attr_count() { return attrs.count(); } void _IDB_CFG::attr_reset() { attrs.clean(); } bool _IDB_CFG::setup() { return true; } void _IDB_CFG::clean() { attr_reset(); } ike-2.2.1+dfsg/source/iked/ike.idb.cpp000066400000000000000000000000001223036517100174160ustar00rootroot00000000000000ike-2.2.1+dfsg/source/iked/ike.idb.exch.cpp000066400000000000000000000156071223036517100203670ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "iked.h" //============================================================================== // generic exchange events //============================================================================== bool _ITH_EVENT_RESEND::func() { bool result = xch->resend(); if( !result ) xch->dec( true ); return result; } //============================================================================== // generic exchange handle list entry //============================================================================== _IDB_XCH::_IDB_XCH() { tunnel = NULL; xch_status = XCH_STATUS_LARVAL; xch_errorcode = XCH_NORMAL; xch_notifycode = 0; initiator = false; exchange = 0; msgid = 0; lstate = 0; xstate = 0; lock.name( "xch" ); // // initialize event info // event_resend.xch = this; event_resend.attempt = 0; } _IDB_XCH::~_IDB_XCH() { event_resend.ipqueue.clean(); } XCH_STATUS _IDB_XCH::status() { lock.lock(); XCH_STATUS cur_status = xch_status; lock.unlock(); return xch_status; } XCH_STATUS _IDB_XCH::status( XCH_STATUS status, XCH_ERRORCODE errorcode, uint16_t notifycode ) { lock.lock(); XCH_STATUS cur_status = xch_status; if( cur_status != XCH_STATUS_DEAD ) { cur_status = xch_status = status; xch_errorcode = errorcode; xch_notifycode = notifycode; if( status == XCH_STATUS_DEAD ) setflags( ENTRY_FLAG_DEAD ); } lock.unlock(); return cur_status; } void _IDB_XCH::new_msgid() { iked.rand_bytes( &msgid, sizeof( msgid ) ); } bool _IDB_XCH::new_msgiv( IDB_PH1 * ph1 ) { if( ph1->evp_cipher == NULL ) return false; unsigned char iv_data[ EVP_MAX_MD_SIZE ]; unsigned long iv_size = EVP_CIPHER_iv_length( ph1->evp_cipher ); EVP_MD_CTX ctx_hash; EVP_DigestInit( &ctx_hash, ph1->evp_hash ); EVP_DigestUpdate( &ctx_hash, ph1->iv.buff(), ph1->iv.size() ); EVP_DigestUpdate( &ctx_hash, &msgid, 4 ); EVP_DigestFinal( &ctx_hash, iv_data, NULL ); EVP_MD_CTX_cleanup( &ctx_hash ); iv.set( iv_data, iv_size ); iked.log.bin( LLOG_DEBUG, LLOG_DECODE, iv.buff(), iv.size(), "== : new %s iv", name() ); return true; } bool _IDB_XCH::resend() { if( event_resend.attempt > iked.retry_count ) { iked.log.txt( LLOG_INFO, "ii : resend limit exceeded for %s exchange\n", name() ); status( XCH_STATUS_DEAD, XCH_FAILED_TIMEOUT, 0 ); return false; } lock.lock(); long count = event_resend.ipqueue.count(); long index = 0; for( ; index < count; index++ ) { PACKET_IP packet; event_resend.ipqueue.get( packet, index ); iked.send_ip( packet ); } lock.unlock(); char txtaddr_l[ LIBIKE_MAX_TEXTADDR ]; char txtaddr_r[ LIBIKE_MAX_TEXTADDR ]; iked.text_addr( txtaddr_l, &tunnel->saddr_l, true ); iked.text_addr( txtaddr_r, &tunnel->saddr_r, true ); iked.log.txt( LLOG_INFO, "-> : resend %i %s packet(s) [%i/%i] %s -> %s\n", count, name(), event_resend.attempt, iked.retry_count, txtaddr_l, txtaddr_r ); event_resend.attempt++; return true; } bool _IDB_XCH::resend_queue( PACKET_IP & packet ) { // // queue a packet // lock.lock(); bool added = event_resend.ipqueue.add( packet ); lock.unlock(); return added; } void _IDB_XCH::resend_purge() { // // purge our queue // lock.lock(); event_resend.ipqueue.clean(); lock.unlock(); } bool _IDB_XCH::resend_sched( bool lock ) { if( lock ) iked.lock_idb.lock(); // // avoid events on dead exchanges // if( status() != XCH_STATUS_DEAD ) { // // add our resend event // event_resend.delay = iked.retry_delay * 1000; if( iked.ith_timer.add( &event_resend ) ) { idb_refcount++; iked.log.txt( LLOG_DEBUG, "DB : %s resend event scheduled ( ref count = %i )\n", name(), idb_refcount ); } } if( lock ) iked.lock_idb.unlock(); return true; } void _IDB_XCH::resend_clear( bool lock, bool purge ) { if( !event_resend.ipqueue.count() ) return; if( lock ) iked.lock_idb.lock(); // // reset our attempt counter // event_resend.attempt = 0; // // remove resend event // if( iked.ith_timer.del( &event_resend ) ) { idb_refcount--; iked.log.txt( LLOG_DEBUG, "DB : %s resend event canceled ( ref count = %i )\n", name(), idb_refcount ); } // // optionally purge our queue // if( purge ) resend_purge(); if( lock ) iked.lock_idb.unlock(); } //============================================================================== // generic sa exchange handle list entry //============================================================================== _IDB_XCH_SA::_IDB_XCH_SA() { dh = NULL; dh_size = 0; } _IDB_XCH_SA::~_IDB_XCH_SA() { } ike-2.2.1+dfsg/source/iked/ike.idb.inform.cpp000066400000000000000000000047311223036517100207260ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "iked.h" // // IDB subclass list section // const char * _IDB_INF::name() { static const char * xname = "informational"; return xname; } IKED_RC_LIST * _IDB_INF::list() { return NULL; } // // class functions // _IDB_INF::_IDB_INF() { } _IDB_INF::~_IDB_INF() { } void _IDB_INF::beg() { } void _IDB_INF::end() { } ike-2.2.1+dfsg/source/iked/ike.idb.lists.cpp000066400000000000000000000270711223036517100205740ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "iked.h" //============================================================================== // basic data list // _IDB_LIST_BDATA::~_IDB_LIST_BDATA() { for( long index = 0; index < count(); index++ ) { IDB_ENTRY_BDATA * bentry = static_cast( get_entry( index ) ); delete bentry; } } bool _IDB_LIST_BDATA::add( BDATA & bdata ) { IDB_ENTRY_BDATA * bentry = new IDB_ENTRY_BDATA; if( bentry == NULL ) return false; *static_cast( bentry ) = bdata; return add_entry( bentry ); } bool _IDB_LIST_BDATA::get( BDATA & bdata, long index ) { IDB_ENTRY_BDATA * bentry = static_cast( get_entry( index ) ); if( bentry == NULL ) return false; bdata = *static_cast( bentry ); return true; } //============================================================================== // IKE proposal list // _IDB_LIST_PROPOSAL::~_IDB_LIST_PROPOSAL() { for( long index = 0; index < count(); index++ ) { IDB_ENTRY_PROPOSAL * pentry = static_cast( get_entry( index ) ); delete pentry; } } bool _IDB_LIST_PROPOSAL::add( IKE_PROPOSAL * proposal, bool pnext ) { IDB_ENTRY_PROPOSAL * pentry = new IDB_ENTRY_PROPOSAL; if( pentry == NULL ) return false; pentry->pnext = pnext; *static_cast( pentry ) = *proposal; add_entry( pentry ); return true; } bool _IDB_LIST_PROPOSAL::get( IKE_PROPOSAL ** proposal, long pindex, uint8_t proto ) { while( pindex < count() ) { IDB_ENTRY_PROPOSAL * pentry = static_cast( get_entry( pindex ) ); if( pentry == NULL ) return false; if( !proto || ( proto == pentry->proto ) ) { *proposal = static_cast( pentry ); return true; } pindex++; } return false; } bool _IDB_LIST_PROPOSAL::nextb( long & bindex, long & pindex, long & pcount ) { if( bindex == -1 ) return false; while( bindex < count() ) { IDB_ENTRY_PROPOSAL * pentry = static_cast( get_entry( bindex ) ); if( pentry == NULL ) return false; if( pentry->pnext ) { long pnumb = pentry->pnumb; pindex = bindex; pcount = 1; bindex++; while( 1 ) { pentry = static_cast( get_entry( bindex ) ); if( pentry == NULL ) { bindex = -1; break; } if( pentry->pnext ) { if( pnumb != pentry->pnumb ) break; pcount++; } bindex++; } return true; } bindex++; } return false; } bool _IDB_LIST_PROPOSAL::nextp( IKE_PROPOSAL ** proposal, long & pindex, long & tindex, long & tcount ) { if( pindex == -1 ) return false; while( pindex < count() ) { IDB_ENTRY_PROPOSAL * pentry = static_cast( get_entry( pindex ) ); if( pentry == NULL ) return false; if( pentry->pnext ) { *proposal = static_cast( pentry ); tindex = pindex; tcount = 1; pindex++; while( 1 ) { pentry = static_cast( get_entry( pindex ) ); if( pentry == NULL ) { pindex = -1; break; } if( pentry->pnext ) break; tcount++; pindex++; } return true; } pindex++; } return false; } bool _IDB_LIST_PROPOSAL::nextt( IKE_PROPOSAL ** proposal, long & tindex ) { if( tindex == -1 ) return false; IDB_ENTRY_PROPOSAL * pentry = static_cast( get_entry( tindex++ ) ); if( pentry == NULL ) return false; *proposal = static_cast( pentry ); pentry = static_cast( get_entry( tindex ) ); if( pentry == NULL ) { tindex = -1; } else { if( pentry->pnext ) tindex = -1; } return true; } //============================================================================== // IKE notification list // _IDB_LIST_NOTIFY::~_IDB_LIST_NOTIFY() { for( long index = 0; index < count(); index++ ) { IDB_ENTRY_NOTIFY * nentry = static_cast( get_entry( index ) ); delete nentry; } } bool _IDB_LIST_NOTIFY::add( IKE_NOTIFY & notify ) { IDB_ENTRY_NOTIFY * nentry = new IDB_ENTRY_NOTIFY; if( nentry == NULL ) return false; nentry->type = notify.type; nentry->code = notify.code; nentry->doi = notify.doi; nentry->proto = notify.proto; nentry->spi = notify.spi; nentry->data = notify.data; return add_entry( nentry ); } bool _IDB_LIST_NOTIFY::get( IKE_NOTIFY & notify, long index ) { IDB_ENTRY_NOTIFY * nentry = static_cast( get_entry( index ) ); if( nentry == NULL ) return false; notify.type = nentry->type; notify.code = nentry->code; notify.doi = nentry->doi; notify.proto = nentry->proto; notify.spi = nentry->spi; notify.data = nentry->data; return true; } //============================================================================== // IKE certificate list // _IDB_LIST_CERT::~_IDB_LIST_CERT() { for( long index = 0; index < count(); index++ ) { IDB_ENTRY_CERT * centry = static_cast( get_entry( index ) ); delete centry; } } bool _IDB_LIST_CERT::add( uint8_t & type, BDATA & data ) { IDB_ENTRY_CERT * centry = new IDB_ENTRY_CERT; if( centry == NULL ) return false; centry->type = type; centry->data = data; return add_entry( centry ); } bool _IDB_LIST_CERT::get( uint8_t & type, BDATA & data, long index ) { IDB_ENTRY_CERT * centry = static_cast( get_entry( index ) ); if( centry == NULL ) return false; type = centry->type; data = centry->data; return true; } //============================================================================== // phase2 ID list // _IDB_LIST_PH2ID::~_IDB_LIST_PH2ID() { for( long index = 0; index < count(); index++ ) { IDB_ENTRY_PH2ID * ientry = static_cast( get_entry( index ) ); delete ientry; } } bool _IDB_LIST_PH2ID::add( IKE_PH2ID & ph2id ) { IDB_ENTRY_PH2ID * ientry = new IDB_ENTRY_PH2ID; if( ientry == NULL ) return false; *static_cast( ientry ) = ph2id; return add_entry( ientry ); } bool _IDB_LIST_PH2ID::get( IKE_PH2ID & ph2id, long index ) { IDB_ENTRY_PH2ID * ientry = static_cast( get_entry( index ) ); if( ientry == NULL ) return false; ph2id = *static_cast( ientry ); return true; } //============================================================================== // network map list ( list of phase2 ID lists ) // _IDB_LIST_NETMAP::~_IDB_LIST_NETMAP() { for( long index = 0; index < count(); index++ ) { IDB_ENTRY_NETMAP * nentry = static_cast( get_entry( index ) ); delete nentry; } } bool _IDB_LIST_NETMAP::add( IDB_LIST_PH2ID * idlist, long mode, BDATA * group ) { IDB_ENTRY_NETMAP * nentry = new IDB_ENTRY_NETMAP; if( nentry == NULL ) return false; if( group != NULL ) nentry->group = *group; nentry->idlist = idlist; nentry->mode = mode; return add_entry( nentry ); } bool _IDB_LIST_NETMAP::get( IDB_ENTRY_NETMAP ** nentry, long index ) { *nentry = static_cast( get_entry( index ) ); return ( *nentry != NULL ); } //============================================================================== // generic iked reference counted list // _IKED_RC_ENTRY::_IKED_RC_ENTRY() { idb_flags = 0; idb_refcount = 0; } _IKED_RC_ENTRY::~_IKED_RC_ENTRY() { } void _IKED_RC_ENTRY::callend() { if( !chkflags( ENTRY_FLAG_ENDCALLED ) ) { setflags( ENTRY_FLAG_ENDCALLED ); end(); } } bool _IKED_RC_ENTRY::add( bool lock ) { if( lock ) list()->lock(); inc( false ); list()->add_entry( this ); iked.log.txt( LLOG_DEBUG, "DB : %s added ( obj count = %i )\n", name(), list()->count() ); if( lock ) list()->unlock(); return true; } void _IKED_RC_ENTRY::inc( bool lock ) { if( lock ) list()->lock(); idb_refcount++; iked.log.txt( LLOG_LOUD, "DB : %s ref increment ( ref count = %i, obj count = %i )\n", name(), idb_refcount, list()->count() ); if( lock ) list()->unlock(); } bool _IKED_RC_ENTRY::dec( bool lock, bool setdel ) { if( lock ) list()->lock(); if( setdel ) setflags( ENTRY_FLAG_DEAD ); if( chkflags( ENTRY_FLAG_DEAD ) ) callend(); assert( idb_refcount > 0 ); idb_refcount--; if( idb_refcount || ( !chkflags( ENTRY_FLAG_DEAD ) && !chkflags( ENTRY_FLAG_IMMEDIATE ) ) ) { iked.log.txt( LLOG_LOUD, "DB : %s ref decrement ( ref count = %i, obj count = %i )\n", name(), idb_refcount, list()->count() ); if( lock ) list()->unlock(); return false; } list()->del_entry( this ); iked.log.txt( LLOG_DEBUG, "DB : %s deleted ( obj count = %i )\n", name(), list()->count() ); if( lock ) list()->unlock(); delete this; return true; } _IKED_RC_LIST::_IKED_RC_LIST() { } _IKED_RC_LIST::~_IKED_RC_LIST() { } void _IKED_RC_LIST::clean() { lock(); long obj_count = count(); long obj_index = 0; for( ; obj_index < obj_count; obj_index++ ) { IKED_RC_ENTRY * entry = static_cast( get_entry( obj_index ) ); entry->inc( false ); if( entry->dec( false, true ) ) { obj_index--; obj_count--; } } unlock(); } bool _IKED_RC_LIST::lock() { return iked.lock_idb.lock(); } bool _IKED_RC_LIST::unlock() { return iked.lock_idb.unlock(); } ike-2.2.1+dfsg/source/iked/ike.idb.peer.cpp000066400000000000000000000115341223036517100203660ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "iked.h" //============================================================================== // ike peer list //============================================================================== IDB_PEER * _IDB_LIST_PEER::get( int index ) { return static_cast( get_entry( index ) ); } bool _IDB_LIST_PEER::find( bool lock, IDB_PEER ** peer, IKE_SADDR * saddr ) { if( peer != NULL ) *peer = NULL; if( lock ) iked.lock_idb.lock(); long peer_count = count(); long peer_index = 0; for( ; peer_index < peer_count; peer_index++ ) { IDB_PEER * tmp_peer = get( peer_index ); // // match the peer address // if( saddr != NULL ) if( has_sockaddr( &tmp_peer->saddr.saddr ) ) if( !cmp_sockaddr( tmp_peer->saddr.saddr, saddr->saddr, false ) ) continue; iked.log.txt( LLOG_DEBUG, "DB : peer found\n" ); // // increase our refrence count // if( peer != NULL ) { tmp_peer->inc( false ); *peer = tmp_peer; } if( lock ) iked.lock_idb.unlock(); return true; } iked.log.txt( LLOG_DEBUG, "DB : peer not found\n" ); if( lock ) iked.lock_idb.unlock(); return false; } //============================================================================== // ike peer list entry //============================================================================== _IDB_PEER::_IDB_PEER( IKE_PEER * set_peer ) { // handle idb zero reference condition iked.lock_run.lock(); if( iked.peercount++ == 0 ) iked.cond_idb.reset(); iked.lock_run.unlock(); if( set_peer != NULL ) *static_cast( this ) = *set_peer; } _IDB_PEER::~_IDB_PEER() { // handle idb zero reference condition iked.lock_run.lock(); if( --iked.peercount == 0 ) iked.cond_idb.alert(); iked.lock_run.unlock(); } //------------------------------------------------------------------------------ // abstract functions from parent class // const char * _IDB_PEER::name() { static const char * xname = "peer"; return xname; } IKED_RC_LIST * _IDB_PEER::list() { return &iked.idb_list_peer; } void _IDB_PEER::beg() { } void _IDB_PEER::end() { iked.log.txt( LLOG_INFO, "DB : removing all peer tunnel references\n" ); // // check for tunnel object references // long tunnel_count = iked.idb_list_tunnel.count(); long tunnel_index = 0; for( ; tunnel_index < tunnel_count; tunnel_index++ ) { // // get the next tunnel in our list // and attempt to match peer ids // IDB_TUNNEL * tunnel = iked.idb_list_tunnel.get( tunnel_index ); if( tunnel->peer == this ) { tunnel->inc( false ); if( tunnel->dec( false, true ) ) { tunnel_index--; tunnel_count--; } } } } ike-2.2.1+dfsg/source/iked/ike.idb.phase1.cpp000066400000000000000000000466151223036517100206240ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "iked.h" //============================================================================== // ike phase1 exchange events //============================================================================== bool _ITH_EVENT_PH1SOFT::func() { iked.log.txt( LLOG_INFO, "ii : phase1 sa is expiring\n" "ii : %04x%04x:%04x%04x\n", htonl( *( long * ) &ph1->cookies.i[ 0 ] ), htonl( *( long * ) &ph1->cookies.i[ 4 ] ), htonl( *( long * ) &ph1->cookies.r[ 0 ] ), htonl( *( long * ) &ph1->cookies.r[ 4 ] ) ); // // if the tunnel peer definition states // that we are to act as a client, replace // this phase1 sa and add it to our list // if( ph1->tunnel->peer->contact == IPSEC_CONTACT_CLIENT ) { IDB_PH1 * addph1 = new IDB_PH1( ph1->tunnel, true, NULL ); addph1->add( false ); iked.process_phase1_send( addph1 ); addph1->dec( false ); } ph1->status( XCH_STATUS_EXPIRING, XCH_NORMAL, 0 ); ph1->dec( true ); // // FIXME : dpd and natt events should stop for // this sa after the new sa negotiates // return false; } bool _ITH_EVENT_PH1HARD::func() { iked.log.txt( LLOG_INFO, "ii : phase1 sa is expired\n" "ii : %04x%04x:%04x%04x\n", htonl( *( long * ) &ph1->cookies.i[ 0 ] ), htonl( *( long * ) &ph1->cookies.i[ 4 ] ), htonl( *( long * ) &ph1->cookies.r[ 0 ] ), htonl( *( long * ) &ph1->cookies.r[ 4 ] ) ); ph1->status( XCH_STATUS_EXPIRED, XCH_FAILED_EXPIRED, 0 ); ph1->dec( true ); return false; } bool _ITH_EVENT_PH1DEAD::func() { iked.log.txt( LLOG_INFO, "ii : phase1 sa is dead\n" "ii : %04x%04x:%04x%04x\n", htonl( *( long * ) &ph1->cookies.i[ 0 ] ), htonl( *( long * ) &ph1->cookies.i[ 4 ] ), htonl( *( long * ) &ph1->cookies.r[ 0 ] ), htonl( *( long * ) &ph1->cookies.r[ 4 ] ) ); ph1->status( XCH_STATUS_DEAD, XCH_FAILED_EXPIRED, 0 ); ph1->dec( true ); return false; } //============================================================================== // ike phase1 exchange handle list //============================================================================== IDB_PH1 * _IDB_LIST_PH1::get( int index ) { return static_cast( get_entry( index ) ); } bool _IDB_LIST_PH1::find( bool lock, IDB_PH1 ** ph1, IDB_TUNNEL * tunnel, XCH_STATUS min, XCH_STATUS max, IKE_COOKIES * cookies ) { if( ph1 != NULL ) *ph1 = NULL; if( lock ) iked.lock_idb.lock(); // // step through our list of sa's // and locate a match // long ph1_count = count(); long ph1_index = 0; for( ; ph1_index < ph1_count; ph1_index++ ) { // // get the next sa in our list // IDB_PH1 * tmp_ph1 = get( ph1_index ); // // match sa minimum status level // if( min != XCH_STATUS_ANY ) if( tmp_ph1->status() < min ) continue; // // match sa maximum status level // if( max != XCH_STATUS_ANY ) if( tmp_ph1->status() > max ) continue; // // match the tunnel id // if( tunnel != NULL ) if( tmp_ph1->tunnel != tunnel ) continue; // // match the cookies // if( cookies != NULL ) { // // next match the initiator cookie // if( memcmp( tmp_ph1->cookies.i, cookies->i, ISAKMP_COOKIE_SIZE ) ) { // // the initiator cookie should // always match if we are to // return a known sa // continue; } // // next match the responder cookie // if( memcmp( tmp_ph1->cookies.r, cookies->r, ISAKMP_COOKIE_SIZE ) ) { // // responder cookie did not match, // if we are the intiator for this // sa, the responder cookie is null // and we are waiting on an sa // payload, it should match // if( tmp_ph1->initiator ) { // // check to see if we solicited // a response from this host // if( !( tmp_ph1->xstate & XSTATE_SENT_SA ) || ( tmp_ph1->xstate & XSTATE_RECV_SA ) ) continue; // // check the responder cookie // for a null value // for( long x = 0; x < ISAKMP_COOKIE_SIZE; x++ ) if( tmp_ph1->cookies.r[ x ] ) continue; // // store the responders cookie in // our existing sa // memcpy( tmp_ph1->cookies.r, cookies->r, ISAKMP_COOKIE_SIZE ); } } } // // looks like we found a match // iked.log.txt( LLOG_DEBUG, "DB : phase1 found\n" ); // // increase our refrence count // if( ph1 != NULL ) { tmp_ph1->inc( false ); *ph1 = tmp_ph1; } if( lock ) iked.lock_idb.unlock(); return true; } iked.log.txt( LLOG_DEBUG, "DB : phase1 not found\n" ); if( lock ) iked.lock_idb.unlock(); return false; } //============================================================================== // ike phase1 exchange handle list entry //============================================================================== _IDB_PH1::_IDB_PH1( IDB_TUNNEL * set_tunnel, bool set_initiator, IKE_COOKIES * set_cookies ) { evp_cipher = NULL; evp_hash = NULL; hash_size = 0; memset( &cookies, 0, sizeof( cookies ) ); vendopts_l.flags = 0; vendopts_r.flags = 0; natt_version = IPSEC_NATT_NONE; natt_pldtype = ISAKMP_PAYLOAD_NONE; hash_size = 0; // // initialize associated tunnel // tunnel = set_tunnel; tunnel->inc( true ); // // initialize initiator value // initiator = set_initiator; // // initialize exchange type // exchange = tunnel->peer->exchange; // // initialize proposal list // iked.phase1_gen_prop( this ); // // initialize local id // iked.gen_ph1id_l( this, ph1id_l ); // // initialize cookie // if( initiator ) iked.rand_bytes( cookies.i, ISAKMP_COOKIE_SIZE ); else { if( set_cookies != NULL ) memcpy( cookies.i, set_cookies->i, ISAKMP_COOKIE_SIZE ); iked.rand_bytes( cookies.r, ISAKMP_COOKIE_SIZE ); } // // initialize nonce data // nonce_l.size( ISAKMP_NONCE_SIZE ); iked.rand_bytes( nonce_l.buff(), ISAKMP_NONCE_SIZE ); // // always advertise as shrew soft // vendopts_l.flag.ssoft = true; // // determine if this is a client tunnel // if( tunnel->peer->contact == IPSEC_CONTACT_CLIENT ) { vendopts_l.flag.netsc = true; vendopts_l.flag.zwall = true; vendopts_l.flag.swind = true; vendopts_l.flag.unity = true; if( tunnel->xconf.opts & IPSEC_OPTS_VEND_CHKPT ) vendopts_l.flag.chkpt = true; } // // determine ike fragmentation negotiation // if( tunnel->peer->frag_ike_mode >= IPSEC_FRAG_ENABLE ) vendopts_l.flag.frag = true; if( tunnel->peer->frag_ike_mode == IPSEC_FRAG_FORCE ) vendopts_r.flag.frag = true; // // determine natt negotiation // if( ( tunnel->peer->natt_mode >= IPSEC_NATT_ENABLE ) && ( tunnel->peer->natt_mode != IPSEC_NATT_FORCE_CISCO ) ) vendopts_l.flag.natt = true; // // determine dpd negotiation // if( tunnel->peer->dpd_mode >= IPSEC_DPD_ENABLE ) vendopts_l.flag.dpdv1 = true; if( tunnel->peer->dpd_mode == IPSEC_DPD_FORCE ) vendopts_r.flag.dpdv1 = true; // // locate the first isakmp proposal // IKE_PROPOSAL * proposal; tunnel->peer->proposals.get( &proposal, 0, ISAKMP_PROTO_ISAKMP ); // // if we are the initiator, obtain // the authentication type // if( initiator ) { auth_id = proposal->auth_id; // // determine xauth negotiation // if( ( proposal->auth_id == XAUTH_AUTH_INIT_PSK ) || ( proposal->auth_id == XAUTH_AUTH_INIT_RSA ) || ( proposal->auth_id == HYBRID_AUTH_INIT_RSA ) ) vendopts_l.flag.xauth = true; } // // aggressive mode must include a kex // payload in the first packet. make // sure we setup the dhgroup in advance // if( tunnel->peer->exchange == ISAKMP_EXCH_AGGRESSIVE ) setup_dhgrp( proposal ); // // initialize event info // event_soft.ph1 = this; event_hard.ph1 = this; event_dead.ph1 = this; // // build text strings for logging // char txtaddr_l[ LIBIKE_MAX_TEXTADDR ]; char txtaddr_r[ LIBIKE_MAX_TEXTADDR ]; iked.text_addr( txtaddr_l, &tunnel->saddr_l, true ); iked.text_addr( txtaddr_r, &tunnel->saddr_r, true ); // // phase 1 created // iked.log.txt( LLOG_DEBUG, "DB : new phase1 ( ISAKMP %s )\n" "DB : exchange type is %s\n" "DB : %s <-> %s\n" "DB : %08x%08x:%08x%08x\n", iked.find_name( NAME_INITIATOR, initiator ), iked.find_name( NAME_EXCHANGE, exchange ), txtaddr_l, txtaddr_r, htonl( *( long * ) &cookies.i[ 0 ] ), htonl( *( long * ) &cookies.i[ 4 ] ), htonl( *( long * ) &cookies.r[ 0 ] ), htonl( *( long * ) &cookies.r[ 4 ] ) ); } _IDB_PH1::~_IDB_PH1() { clean(); // // derefrence our tunnel // tunnel->dec( false ); } //------------------------------------------------------------------------------ // abstract functions from parent class // const char * _IDB_PH1::name() { static const char * xname = "phase1"; return xname; } IKED_RC_LIST * _IDB_PH1::list() { return &iked.idb_list_ph1; } void _IDB_PH1::beg() { } void _IDB_PH1::end() { // // clear the resend queue // resend_clear( false, true ); // // remove scheduled events // if( iked.ith_timer.del( &event_soft ) ) { idb_refcount--; iked.log.txt( LLOG_DEBUG, "DB : phase1 soft event canceled ( ref count = %i )\n", idb_refcount ); } if( iked.ith_timer.del( &event_hard ) ) { idb_refcount--; iked.log.txt( LLOG_DEBUG, "DB : phase1 hard event canceled ( ref count = %i )\n", idb_refcount ); } if( iked.ith_timer.del( &event_dead ) ) { idb_refcount--; iked.log.txt( LLOG_DEBUG, "DB : phase1 dead event canceled ( ref count = %i )\n", idb_refcount ); } // // send a delete message if required // if( ( lstate & LSTATE_HASKEYS ) && ( xch_errorcode != XCH_FAILED_EXPIRED ) && ( xch_errorcode != XCH_FAILED_PEER_DELETE ) ) iked.inform_new_delete( this, NULL ); // // if this sa has reached maturity, // locate any config handles used by // this sa and delete them // // FIXME : There must be a better way // if( lstate & LSTATE_HASKEYS ) { // // FIXME : Use find here // long cfg_count = iked.idb_list_cfg.count(); long cfg_index = 0; for( ; cfg_index < cfg_count; cfg_index++ ) { // // get the next config in our list // and attempt to match by pointer // IDB_CFG * cfg = iked.idb_list_cfg.get( cfg_index ); if( cfg->ph1ref == this ) { cfg->inc( false ); cfg->status( XCH_STATUS_DEAD, XCH_FAILED_PENDING, 0 ); if( cfg->dec( false ) ) { cfg_index--; cfg_count--; } } } } // // if this sa never reached maturity, // locate any pending phase2 handles // for this tunnel and delete them // // FIXME : This should be timer driven // if( !( lstate & LSTATE_HASKEYS ) ) { // // FIXME : Use find here // long ph2_count = iked.idb_list_ph2.count(); long ph2_index = 0; for( ; ph2_index < ph2_count; ph2_index++ ) { // // get the next phase2 in our list // and attempt to match tunnel ids // IDB_PH2 * ph2 = iked.idb_list_ph2.get( ph2_index ); if( ( ph2->tunnel == tunnel ) && ( ph2->status() == XCH_STATUS_PENDING ) ) { ph2->inc( false ); ph2->status( XCH_STATUS_DEAD, XCH_FAILED_PENDING, 0 ); if( ph2->dec( false ) ) { ph2_index--; ph2_count--; } } } } // // log deletion // if( xch_errorcode != XCH_FAILED_EXPIRED ) iked.log.txt( LLOG_INFO, "ii : phase1 removal before expire time\n" ); else iked.log.txt( LLOG_INFO, "ii : phase1 removal after expire time\n" ); // // if we have negotiated a replacement // isakmp sa, change our delete status // to expired. some gateways will send // a delete message for the old sa and // we don't want to treat this as an // error condition below. // if( xch_errorcode == XCH_FAILED_PEER_DELETE ) if( iked.idb_list_ph1.find( false, NULL, tunnel, XCH_STATUS_MATURE, XCH_STATUS_MATURE, NULL ) ) xch_errorcode = XCH_FAILED_EXPIRED; // // if this is a client tunnel and there // was an error negotiating phase1, set // a close error message and wakeup the // client thread // if( tunnel->peer->contact == IPSEC_CONTACT_CLIENT ) { if( xch_errorcode != XCH_FAILED_EXPIRED ) { tunnel->close = xch_errorcode; if( tunnel->ikei != NULL ) tunnel->ikei->wakeup(); } } } //------------------------------------------------------------------------------ // additional functions // bool _IDB_PH1::setup_dhgrp( IKE_PROPOSAL * proposal ) { // // initialize dh group // if( !dh_init( proposal->dhgr_id, &dh, &dh_size ) ) { iked.log.txt( LLOG_ERROR, "ii : failed to setup DH group\n" ); return false; } xl.size( dh_size ); long result = BN_bn2bin( dh->pub_key, xl.buff() ); // // fixup public buffer alignment // if( dh_size > result ) { iked.log.txt( LLOG_DEBUG, "ww : short DH public value\n" ); xl.size( result ); xl.ins( 0, dh_size - result ); } return true; } bool _IDB_PH1::setup_xform( IKE_PROPOSAL * proposal ) { // // select cipher and hash crypto objects // switch( proposal->ciph_id ) { case IKE_CIPHER_DES: evp_cipher = EVP_des_cbc(); break; case IKE_CIPHER_BLOWFISH: evp_cipher = EVP_bf_cbc(); break; case IKE_CIPHER_3DES: evp_cipher = EVP_des_ede3_cbc(); break; case IKE_CIPHER_CAST: evp_cipher = EVP_cast5_cbc(); break; case IKE_CIPHER_AES: { switch( proposal->ciph_kl ) { case 128: evp_cipher = EVP_aes_128_cbc(); break; case 192: evp_cipher = EVP_aes_192_cbc(); break; case 256: evp_cipher = EVP_aes_256_cbc(); break; default: return false; } break; } default: return false; } switch( proposal->hash_id ) { case IKE_HASH_MD5: evp_hash = EVP_md5(); break; case IKE_HASH_SHA1: evp_hash = EVP_sha1(); break; case IKE_HASH_SHA2_256: evp_hash = EVP_sha256(); break; case IKE_HASH_SHA2_384: evp_hash = EVP_sha384(); break; case IKE_HASH_SHA2_512: evp_hash = EVP_sha512(); break; default: return false; } hash_size = EVP_MD_size( evp_hash ); return true; } void _IDB_PH1::clean() { if( dh ) { DH_free( dh ); dh = NULL; } nonce_l.del( true ); nonce_r.del( true ); xl.del( true ); xr.del( true ); hash_l.del( true ); hash_r.del( true ); hda.del( true );; idi.del( true ); idr.del( true ); natd_hash_l.clean(); natd_hash_r.clean(); certs_r.clean(); creqs_r.clean(); sign_r.del( true ); } bool _IDB_PH1::frag_add( unsigned char * data, unsigned long size, long index, bool last ) { // // create our new ike fragment // IKE_FRAG * frag = new IKE_FRAG; if( frag == NULL ) return false; // // set the fragment info // frag->index = index; frag->last = last; frag->data.set( data, size ); // // add the fragment to our list // return frags.add_entry( frag ); } bool _IDB_PH1::frag_get( PACKET_IKE & packet ) { bool frag_done = false; int frag_index = 1; // // check to see if we have a // complete ike packet // while( !frag_done ) { // // step through all fragments // and look for the next index // int list_count = frags.count(); int list_index = 0; for( ; list_index < list_count; list_index++ ) { IKE_FRAG * frag = static_cast( frags.get_entry( list_index ) ); // // does this match our next index // if( frag->index == frag_index ) { // // is this the last fragment // if( frag->last ) { frag_done = true; break; } // // not the last fragment, look // for the next one // frag_index++; // // reset the fragement list index // list_index = -1; continue; } } // // if we made a complete pass through // our fragment list and did not find // the next fragment, we dont have a // complete packet yet // if( list_index == list_count ) return false; } // // reassemble the packet from ike // fragments stored in our list // packet.reset(); frag_done = false; frag_index = 1; while( !frag_done ) { // // step through all fragments // and look for the next index // int list_count = frags.count(); int list_index = 0; for( ; list_index < list_count; list_index++ ) { IKE_FRAG * frag = static_cast( frags.get_entry( list_index ) ); // // does this match our next index // if( frag->index == frag_index ) { // // add the data to our packet // packet.add( frag->data ); // // is this the last fragment // if( frag->last ) { frag_done = true; break; } // // not the last fragment, look // for the next one // frag_index++; // // reset the fragement list index // list_index = -1; continue; } } } // // purge our fragment list // frags.clean(); return true; } ike-2.2.1+dfsg/source/iked/ike.idb.phase2.cpp000066400000000000000000000235341223036517100206200ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "iked.h" //============================================================================== // ike phase2 exchange events //============================================================================== bool _ITH_EVENT_PH2SOFT::func() { iked.log.txt( LLOG_INFO, "ii : phase2 sa will expire in %i seconds\n", diff ); if( ph2->nailed ) iked.pfkey_init_phase2( true, IPSEC_POLICY_IPSEC, ph2->plcyid_out, 0 ); ph2->status( XCH_STATUS_EXPIRING, XCH_NORMAL, 0 ); ph2->dec( true ); return false; } bool _ITH_EVENT_PH2HARD::func() { iked.log.txt( LLOG_INFO, "ii : phase2 sa is dead\n" ); ph2->status( XCH_STATUS_DEAD, XCH_FAILED_EXPIRED, 0 ); ph2->dec( true ); return false; } //============================================================================== // ike phase2 exchange handle list //============================================================================== IDB_PH2 * _IDB_LIST_PH2::get( int index ) { return static_cast( get_entry( index ) ); } bool _IDB_LIST_PH2::find( bool lock, IDB_PH2 ** ph2, IDB_TUNNEL * tunnel, XCH_STATUS min, XCH_STATUS max, u_int32_t * seqid, uint32_t * msgid, IKE_SPI * spi_l, IKE_SPI * spi_r ) { if( ph2 != NULL ) *ph2 = NULL; if( lock ) iked.lock_idb.lock(); // // step through our list of sa's // and locate a match // long ph2_count = count(); long ph2_index = 0; for( ; ph2_index < ph2_count; ph2_index++ ) { // // get the next sa in our list // IDB_PH2 * tmp_ph2 = get( ph2_index ); // // match sa minimum status level // if( min != XCH_STATUS_ANY ) if( tmp_ph2->status() < min ) continue; // // match sa maximum status level // if( max != XCH_STATUS_ANY ) if( tmp_ph2->status() > max ) continue; // // match the tunnel id // if( tunnel != NULL ) if( tmp_ph2->tunnel != tunnel ) continue; // // match the seqid // if( seqid != NULL ) if( ( tmp_ph2->seqid_in != *seqid ) && ( tmp_ph2->seqid_out != *seqid ) ) continue; // // match the msgid // if( msgid != NULL ) if( tmp_ph2->msgid != *msgid ) continue; // // match a local spi value // if( spi_l != NULL ) { IKE_PROPOSAL * proposal; long pindex = 0; bool found; while( ( found = tmp_ph2->plist_l.get( &proposal, pindex++ ) ) ) if( proposal->spi.size == spi_l->size ) if( !memcmp( &proposal->spi, spi_l, spi_l->size ) ) break; if( !found ) continue; } // // match a remote spi value // if( spi_r != NULL ) { IKE_PROPOSAL * proposal; long pindex = 0; bool found; while( ( found = tmp_ph2->plist_r.get( &proposal, pindex++ ) ) ) if( proposal->spi.size == spi_r->size ) if( !memcmp( &proposal->spi, spi_r, spi_r->size ) ) break; if( !found ) continue; } iked.log.txt( LLOG_DEBUG, "DB : phase2 found\n" ); // // increase our refrence count // if( ph2 != NULL ) { tmp_ph2->inc( false ); *ph2 = tmp_ph2; } if( lock ) iked.lock_idb.unlock(); return true; } iked.log.txt( LLOG_DEBUG, "DB : phase2 not found\n" ); if( lock ) iked.lock_idb.unlock(); return false; } void _IDB_LIST_PH2::flush() { iked.lock_idb.lock(); long ph2_count = count(); long ph2_index = 0; for( ; ph2_index < ph2_count; ph2_index++ ) { IDB_PH2 * ph2 = get( ph2_index ); ph2->inc( false ); ph2->status( XCH_STATUS_DEAD, XCH_FAILED_FLUSHED, 0 ); if( ph2->dec( false ) ) { ph2_index--; ph2_count--; } } iked.lock_idb.unlock(); } //============================================================================== // ike phase2 exchange handle list entry //============================================================================== _IDB_PH2::_IDB_PH2( IDB_TUNNEL * set_tunnel, bool set_initiator, uint32_t set_msgid, uint32_t set_seqid_in ) { memset( &cookies, 0, sizeof( cookies ) ); seqid_in = 0; seqid_out = 0; plcyid_in = 0; plcyid_out = 0; nailed = false; spicount = 0; dhgr_id = 0; // // initialize the tunnel id // tunnel = set_tunnel; tunnel->inc( true ); // // initialize sa // initiator = set_initiator; exchange = ISAKMP_EXCH_QUICK; // // initialize msgid // if( set_msgid ) msgid = set_msgid; else new_msgid(); // // initialize seqids // if( set_seqid_in ) seqid_in = set_seqid_in; else iked.rand_bytes( &seqid_in, sizeof( seqid_in ) ); iked.rand_bytes( &seqid_out, sizeof( seqid_out ) ); // // initialize nonce data // nonce_l.size( ISAKMP_NONCE_SIZE ); iked.rand_bytes( nonce_l.buff(), ISAKMP_NONCE_SIZE ); // // initialize event info // event_soft.ph2 = this; event_hard.ph2 = this; // // phase 2 created // iked.log.txt( LLOG_DEBUG, "DB : new phase2 ( IPSEC %s )\n", iked.find_name( NAME_INITIATOR, initiator ) ); } _IDB_PH2::~_IDB_PH2() { clean(); // // dereference our tunnel // tunnel->dec( false ); } //------------------------------------------------------------------------------ // abstract functions from parent class // const char * _IDB_PH2::name() { static const char * xname = "phase2"; return xname; } IKED_RC_LIST * _IDB_PH2::list() { return &iked.idb_list_ph2; } void _IDB_PH2::beg() { } void _IDB_PH2::end() { // // clear the resend queue // resend_clear( false, true ); // // remove scheduled events // if( iked.ith_timer.del( &event_soft ) ) { idb_refcount--; iked.log.txt( LLOG_DEBUG, "DB : phase2 soft event canceled ( ref count = %i )\n", idb_refcount ); } if( iked.ith_timer.del( &event_hard ) ) { idb_refcount--; iked.log.txt( LLOG_DEBUG, "DB : phase2 hard event canceled ( ref count = %i )\n", idb_refcount ); } // // send a delete message if required // if( ( lstate & LSTATE_HASKEYS ) && ( xch_errorcode != XCH_FAILED_EXPIRED ) && ( xch_errorcode != XCH_FAILED_PEER_DELETE ) ) { IDB_PH1 * ph1; if( iked.idb_list_ph1.find( false, &ph1, tunnel, XCH_STATUS_MATURE, XCH_STATUS_EXPIRED, NULL ) ) { iked.inform_new_delete( ph1, this ); ph1->dec( false ); } } // // inform pfkey interface // if( ( lstate & LSTATE_HASKEYS ) && ( xch_errorcode != XCH_FAILED_FLUSHED ) && ( xch_errorcode != XCH_FAILED_EXPIRED ) ) iked.pfkey_send_delete( this ); // // update tunnel stats // if( lstate & LSTATE_HASKEYS ) tunnel->stats.sa_dead++; else tunnel->stats.sa_fail++; // // log deletion // if( xch_errorcode != XCH_FAILED_EXPIRED ) iked.log.txt( LLOG_INFO, "ii : phase2 removal before expire time\n" ); else iked.log.txt( LLOG_INFO, "ii : phase2 removal after expire time\n" ); } //------------------------------------------------------------------------------ // additional functions // bool _IDB_PH2::setup_dhgrp() { // // if we are performing pfs, initialize dh group // if( dhgr_id ) { if( !dh_init( dhgr_id, &dh, &dh_size ) ) { iked.log.txt( LLOG_ERROR, "ii : failed to setup PFS DH group\n" ); return false; } xl.size( dh_size ); long result = BN_bn2bin( dh->pub_key, xl.buff() ); // // fixup public buffer alignment // if( dh_size > result ) { iked.log.txt( LLOG_DEBUG, "ww : short PFS DH public value\n" ); xl.size( result ); xl.ins( 0, dh_size - result ); } } return true; } void _IDB_PH2::clean() { if( dh ) { DH_free( dh ); dh = NULL; } nonce_l.del( true ); nonce_r.del( true ); xl.del( true ); xr.del( true ); hash_l.del( true ); hash_r.del( true ); hda.del( true ); } ike-2.2.1+dfsg/source/iked/ike.idb.policy.cpp000066400000000000000000000130231223036517100207250ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "iked.h" //============================================================================== // policy list //============================================================================== IDB_POLICY * _IDB_LIST_POLICY::get( int index ) { return static_cast( get_entry( index ) ); } bool _IDB_LIST_POLICY::find( bool lock, IDB_POLICY ** policy, long dir, u_int16_t type, u_int32_t * seq, u_int32_t * plcyid, IKE_SADDR * src, IKE_SADDR * dst, IKE_PH2ID * ids, IKE_PH2ID * idd ) { if( policy != NULL ) *policy = NULL; if( lock ) iked.lock_idb.lock(); // // step through our list of policys // and see if they match the msgid // long policy_count = count(); long policy_index = 0; for( ; policy_index < policy_count; policy_index++ ) { // // get the next policy in our list // IDB_POLICY * tmp_policy = get( policy_index ); // // compare policy direction // if( tmp_policy->sp.dir != dir ) continue; // // compare policy type // if( tmp_policy->sp.type != type ) continue; // // compare policy sequence // if( seq != NULL ) if( *seq != tmp_policy->seq ) continue; // // compare policy id // if( plcyid != NULL ) if( *plcyid != tmp_policy->sp.id ) continue; // // compare the policy endpoint addresses // IKE_SADDR psrc; IKE_SADDR pdst; if( ( src != NULL ) || ( dst != NULL ) ) iked.policy_get_addrs( tmp_policy, psrc, pdst ); if( src != NULL ) if( !cmp_ikeaddr( psrc, *src, false ) ) continue; if( dst != NULL ) if( !cmp_ikeaddr( pdst, *dst, false ) ) continue; // // compare ipv4 ids ( non-exact ) // if( ids != NULL ) { IKE_PH2ID ph2id; iked.paddr_ph2id( tmp_policy->paddr_src, ph2id ); if( !iked.cmp_ph2id( ph2id, *ids, false ) ) continue; } if( idd != NULL ) { IKE_PH2ID ph2id; iked.paddr_ph2id( tmp_policy->paddr_dst, ph2id ); if( !iked.cmp_ph2id( ph2id, *idd, false ) ) continue; } iked.log.txt( LLOG_DEBUG, "DB : policy found\n" ); // // increase our refrence count // if( policy != NULL ) { tmp_policy->inc( false ); *policy = tmp_policy; } if( lock ) iked.lock_idb.unlock(); return true; } iked.log.txt( LLOG_DEBUG, "DB : policy not found\n" ); if( lock ) iked.lock_idb.unlock(); return false; } void _IDB_LIST_POLICY::flush() { clean(); } //============================================================================== // policy list entry //============================================================================== _IDB_POLICY::_IDB_POLICY( PFKI_SPINFO * spinfo ) { memset( &paddr_src, 0, sizeof( paddr_src ) ); memset( &paddr_dst, 0, sizeof( paddr_dst ) ); memset( &sp, 0, sizeof( sp ) ); memset( xforms, 0, sizeof( xforms ) ); flags = 0; iked.rand_bytes( &spinfo->seq, sizeof( spinfo->seq ) ); if( spinfo != NULL ) *static_cast( this ) = *spinfo; } _IDB_POLICY::~_IDB_POLICY() { } //------------------------------------------------------------------------------ // abstract functions from parent class // const char * _IDB_POLICY::name() { static const char * xname = "policy"; return xname; } IKED_RC_LIST * _IDB_POLICY::list() { return &iked.idb_list_policy; } void _IDB_POLICY::beg() { } void _IDB_POLICY::end() { } ike-2.2.1+dfsg/source/iked/ike.idb.tunnel.cpp000066400000000000000000000327071223036517100207450ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "iked.h" //============================================================================== // tunnel events //============================================================================== bool _ITH_EVENT_TUNDHCP::func() { // // check for tunnel close or // retry timeout // if( tunnel->close || ( retry > 6 ) ) { tunnel->close = XCH_FAILED_DHCPCONFIG; tunnel->ikei->wakeup(); tunnel->dec( true ); return false; } // // check renew time // time_t current = time( NULL ); if( current > renew ) iked.process_dhcp_recv( tunnel ); if( current > renew ) iked.process_dhcp_send( tunnel ); return true; } void _ITH_EVENT_TUNDPD::next() { // // remove this event // if( iked.ith_timer.del( this ) ) { // // reset the attempt counter // attempt = 0; // // readd this event // delay = tunnel->peer->dpd_delay * 1000; iked.ith_timer.add( this ); char txtaddr_r[ LIBIKE_MAX_TEXTADDR ]; iked.text_addr( txtaddr_r, &tunnel->saddr_r, true ); iked.log.txt( LLOG_DEBUG, "ii : next tunnel DPD request in %i secs for peer %s\n", tunnel->peer->dpd_delay, txtaddr_r ); } } bool _ITH_EVENT_TUNDPD::func() { // // check our attempt counter // if( attempt == tunnel->peer->dpd_retry ) { char txtaddr_r[ LIBIKE_MAX_TEXTADDR ]; iked.text_addr( txtaddr_r, &tunnel->saddr_r, true ); iked.log.txt( LLOG_ERROR, "!! : tunnel DPD timeout for peer %s\n", txtaddr_r ); tunnel->close = XCH_FAILED_PEER_DEAD; tunnel->ikei->wakeup(); tunnel->dec( true ); return false; } // // locate mature phase1 handle // IDB_PH1 * ph1 = NULL; if( !iked.idb_list_ph1.find( true, &ph1, tunnel, XCH_STATUS_MATURE, XCH_STATUS_EXPIRING, NULL ) ) { char txtaddr_r[ LIBIKE_MAX_TEXTADDR ]; iked.text_addr( txtaddr_r, &tunnel->saddr_r, true ); iked.log.txt( LLOG_ERROR, "!! : unable to locate phase1 to process DPD for peer %s\n", txtaddr_r ); return true; } // // determine the next dpd delay // if( !attempt ) delay = tunnel->peer->dpd_delay * 1000; else { long retry_secs = tunnel->peer->dpd_retry - attempt; delay = retry_secs * 1000; char txtaddr_r[ LIBIKE_MAX_TEXTADDR ]; iked.text_addr( txtaddr_r, &tunnel->saddr_r, true ); iked.log.txt( LLOG_DEBUG, "ii : next tunnel DPD retry in %i secs for peer %s\n", retry_secs, txtaddr_r ); } // // add new sequence number and send // uint32_t dpdseq = htonl( ++sequence ); BDATA bdata; bdata.add( &dpdseq, sizeof( dpdseq ) ); iked.inform_new_notify( ph1, NULL, ISAKMP_N_DPD_R_U_THERE, &bdata ); iked.log.txt( LLOG_DEBUG, "ii : DPD ARE-YOU-THERE sequence %08x requested\n", sequence ); ph1->dec( true ); attempt++; return true; } bool _ITH_EVENT_TUNNATT::func() { // // locate mature phase1 handle // IDB_PH1 * ph1 = NULL; if( !iked.idb_list_ph1.find( true, &ph1, tunnel, XCH_STATUS_MATURE, XCH_STATUS_EXPIRING, NULL ) ) { char txtaddr_r[ LIBIKE_MAX_TEXTADDR ]; iked.text_addr( txtaddr_r, &tunnel->saddr_r, true ); iked.log.txt( LLOG_ERROR, "!! : unable to locate phase1 to process NAT-T for peer %s\n", txtaddr_r ); return true; } // // determine natt ports // IKE_SADDR saddr_l = ph1->tunnel->saddr_l; IKE_SADDR saddr_r = ph1->tunnel->saddr_r; if( ph1->tunnel->natt_version == IPSEC_NATT_CISCO ) { iked.socket_lookup_port( saddr_l, true ); set_sockport( saddr_r.saddr, ph1->tunnel->peer->natt_port ); } // // encapsulate natt keep alive // PACKET_UDP packet_udp; packet_udp.write( saddr_l.saddr4.sin_port, saddr_r.saddr4.sin_port ); packet_udp.add_byte( 0xff ); packet_udp.done( saddr_l.saddr4.sin_addr, saddr_r.saddr4.sin_addr ); PACKET_IP packet_ip; packet_ip.write( saddr_l.saddr4.sin_addr, saddr_r.saddr4.sin_addr, iked.ident++, PROTO_IP_UDP ); packet_ip.add( packet_udp ); packet_ip.done(); // // send ike packet // char txtaddr_l[ LIBIKE_MAX_TEXTADDR ]; char txtaddr_r[ LIBIKE_MAX_TEXTADDR ]; iked.text_addr( txtaddr_l, &saddr_l, true ); iked.text_addr( txtaddr_r, &saddr_r, true ); iked.log.txt( LLOG_DEBUG, "-> : send NAT-T:KEEP-ALIVE packet %s -> %s\n", txtaddr_l, txtaddr_r ); iked.send_ip( packet_ip ); ph1->dec( true ); return true; } bool _ITH_EVENT_TUNSTATS::func() { // // check tunnel status and send // message once every second // if( !( tunnel->close ) ) { tunnel->stats.peer = tunnel->saddr_r; tunnel->stats.natt = tunnel->natt_version; IKEI_MSG msg; msg.set_stats( &tunnel->stats ); tunnel->ikei->send_message( msg ); } return true; } //============================================================================== // tunnel list //============================================================================== IDB_TUNNEL * _IDB_LIST_TUNNEL::get( int index ) { return static_cast( get_entry( index ) ); } bool _IDB_LIST_TUNNEL::find( bool lock, IDB_TUNNEL ** tunnel, long * tunnelid, IKE_SADDR * saddr, bool port, bool suspended ) { if( tunnel != NULL ) *tunnel = NULL; if( lock ) iked.lock_idb.lock(); long tunnel_count = count(); long tunnel_index = 0; for( ; tunnel_index < tunnel_count; tunnel_index++ ) { IDB_TUNNEL * tmp_tunnel = get( tunnel_index ); // // match the tunnel id // if( tunnelid != NULL ) if( tmp_tunnel->tunnelid != *tunnelid ) continue; // // match the peer address // if( saddr != NULL ) if( !cmp_sockaddr( tmp_tunnel->saddr_r.saddr, saddr->saddr, port ) ) continue; // // match suspended value // if( suspended ) if( !tmp_tunnel->suspended ) continue; iked.log.txt( LLOG_DEBUG, "DB : tunnel found\n" ); // // increase our refrence count // if( tunnel != NULL ) { tmp_tunnel->inc( false ); *tunnel = tmp_tunnel; } if( lock ) iked.lock_idb.unlock(); return true; } iked.log.txt( LLOG_DEBUG, "DB : tunnel not found\n" ); if( lock ) iked.lock_idb.unlock(); return false; } //============================================================================== // tunnel list entry //============================================================================== _IDB_TUNNEL::_IDB_TUNNEL( IDB_PEER * set_peer, IKE_XCONF * set_xconf, IKE_SADDR * set_saddr_l, IKE_SADDR * set_saddr_r ) { ikei = NULL; #ifdef OPT_DTP dtpi = NULL; #endif adapter = NULL; // // tunnels are removed immediately // when the refcount reaches zero // setflags( ENTRY_FLAG_IMMEDIATE ); tstate = 0; lstate = 0; close = XCH_NORMAL; suspended = false; natt_version = IPSEC_NATT_NONE; dhcp_sock = INVALID_SOCKET; force_all = false; // // initialize the tunnel id // tunnelid = iked.tunnelid++; saddr_l = *set_saddr_l; saddr_r = *set_saddr_r; peer = set_peer; peer->inc( true ); memset( &stats, 0, sizeof( stats ) ); memset( &xconf, 0, sizeof( xconf ) ); #ifdef WIN32 memset( &nscfg, 0, sizeof( nscfg ) ); #endif // // setup xconf // if( set_xconf != NULL ) xconf = *set_xconf; if( !( xconf.opts & IPSEC_OPTS_ADDR ) ) { if( peer->contact == IPSEC_CONTACT_CLIENT ) xconf.addr = saddr_l.saddr4.sin_addr; else xconf.addr = saddr_r.saddr4.sin_addr; xconf.mask.s_addr = 0xffffffff; } // // initialize event info // event_stats.tunnel = this; event_dpd.tunnel = this; event_dpd.sequence = 0; event_dpd.attempt = 0; event_natt.tunnel = this; event_dhcp.tunnel = this; event_dhcp.lease = 0; event_dhcp.renew = 0; event_dhcp.retry = 0; // // determine dpd negotiation // if( peer->dpd_mode >= IPSEC_DPD_ENABLE ) { iked.rand_bytes( &event_dpd.sequence, sizeof( event_dpd.sequence ) ); event_dpd.sequence >>= 2; } // // setup our filter // #ifdef WIN32 iked.tunnel_filter_add( this, false ); #endif } _IDB_TUNNEL::~_IDB_TUNNEL() { // // cleanup our filter // #ifdef WIN32 iked.tunnel_filter_del( this ); #endif // // dereference our peer // peer->dec( false ); } //------------------------------------------------------------------------------ // abstract functions from parent class // const char * _IDB_TUNNEL::name() { static const char * xname = "tunnel"; return xname; } IKED_RC_LIST * _IDB_TUNNEL::list() { return &iked.idb_list_tunnel; } void _IDB_TUNNEL::beg() { } void _IDB_TUNNEL::end() { // // remove scheduled events // if( iked.ith_timer.del( &event_dhcp ) ) { idb_refcount--; iked.log.txt( LLOG_DEBUG, "DB : tunnel dhcp event canceled ( ref count = %i )\n", idb_refcount ); } if( iked.ith_timer.del( &event_dpd ) ) { idb_refcount--; iked.log.txt( LLOG_DEBUG, "DB : tunnel dpd event canceled ( ref count = %i )\n", idb_refcount ); } if( iked.ith_timer.del( &event_natt ) ) { idb_refcount--; iked.log.txt( LLOG_DEBUG, "DB : tunnel natt event canceled ( ref count = %i )\n", idb_refcount ); } if( iked.ith_timer.del( &event_stats ) ) { idb_refcount--; iked.log.txt( LLOG_DEBUG, "DB : tunnel stats event canceled ( ref count = %i )\n", idb_refcount ); } // // check for config object references // iked.log.txt( LLOG_INFO, "DB : removing tunnel config references\n" ); long cfg_count = iked.idb_list_cfg.count(); long cfg_index = 0; for( ; cfg_index < cfg_count; cfg_index++ ) { // // get the next config in our list // and attempt to match tunnel ids // IDB_CFG * cfg = iked.idb_list_cfg.get( cfg_index ); if( cfg->tunnel == this ) { cfg->inc( false ); cfg->status( XCH_STATUS_DEAD, XCH_FAILED_USERREQ, 0 ); if( cfg->dec( false ) ) { cfg_index--; cfg_count--; } } } // // check for phase2 object references // iked.log.txt( LLOG_INFO, "DB : removing tunnel phase2 references\n" ); long ph2_count = iked.idb_list_ph2.count(); long ph2_index = 0; for( ; ph2_index < ph2_count; ph2_index++ ) { // // get the next phase2 in our list // and attempt to match tunnel ids // IDB_PH2 * ph2 = iked.idb_list_ph2.get( ph2_index ); if( ph2->tunnel == this ) { ph2->inc( false ); ph2->status( XCH_STATUS_DEAD, XCH_FAILED_USERREQ, 0 ); if( ph2->dec( false ) ) { ph2_index--; ph2_count--; } } } // // check for phase1 object references // iked.log.txt( LLOG_INFO, "DB : removing tunnel phase1 references\n" ); long ph1_count = iked.idb_list_ph1.count(); long ph1_index = 0; for( ; ph1_index < ph1_count; ph1_index++ ) { // // get the next phase1 in our list // and attempt to match tunnel ids // IDB_PH1 * ph1 = iked.idb_list_ph1.get( ph1_index ); if( ph1->tunnel == this ) { ph1->inc( false ); ph1->status( XCH_STATUS_DEAD, XCH_FAILED_USERREQ, 0 ); if( ph1->dec( false ) ) { ph1_index--; ph1_count--; } } } // // cleaup client tunnels // if( peer->contact == IPSEC_CONTACT_SERVER ) { if( peer->plcy_mode != POLICY_MODE_DISABLE ) iked.policy_list_remove( this, false ); if( xconf.opts & IPSEC_OPTS_ADDR ) peer->xconf_source->pool4_rel( xconf.addr ); } } ike-2.2.1+dfsg/source/iked/ike.io.admin.cpp000066400000000000000000000504441223036517100203770ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "iked.h" // // ike client io thread // long ITH_IKES::iked_func( void * arg ) { IKED * iked = ( IKED * ) arg; return iked->loop_ipc_server(); } long _IKED::loop_ipc_server() { // // begin admin thread // loop_ref_inc( "ipc server" ); while( true ) { IKEI * ikei; long result = ikes.inbound( &ikei ); switch( result ) { case IPCERR_OK: ith_ikec.exec( ikei ); continue; case IPCERR_NODATA: continue; } break; } loop_ref_dec( "ipc server" ); return true; } long ITH_IKEC::iked_func( void * arg ) { IKEI * ikei = ( IKEI * ) arg; long result = iked.loop_ipc_client( ikei ); return result; } long _IKED::loop_ipc_client( IKEI * ikei ) { loop_ref_inc( "ipc client" ); // // temporary configuration data // IKE_XCONF ike_xconf; memset( &ike_xconf, 0, sizeof( ike_xconf ) ); IKE_PEER ike_peer; memset( &ike_peer, 0, sizeof( ike_peer ) ); BDATA xuser; BDATA xpass; BDATA psk; BDATA cert_r; BDATA cert_l; BDATA cert_k; BDATA iddata_r; BDATA iddata_l; IDB_LIST_PROPOSAL proposals; IDB_LIST_PH2ID idlist_incl; IDB_LIST_PH2ID idlist_excl; IDB_LIST_DOMAIN domains; IKE_SADDR saddr_l; BDATA fpass; // // db configuration objects // IDB_PEER * peer = NULL; IDB_TUNNEL * tunnel = NULL; // // enter client ctrl loop // IKEI_MSG msg; bool detach = false; bool suspended = false; while( !detach ) { long result; // // check for tunnel close // if( tunnel != NULL ) if( tunnel->close ) break; // // get the next message // result = ikei->recv_message( msg ); if( result == IPCERR_CLOSED ) break; if( result == IPCERR_NODATA ) continue; if( result == IPCERR_OK ) { // // set default result // result = IKEI_RESULT_FAILED; // // handle message by type // switch( msg.header.type ) { // // client config message // case IKEI_MSGID_CLIENT: { log.txt( LLOG_INFO, "contact = IPSEC_CONTACT_CLIENT; peer->psk = psk; peer->cert_r = cert_r; peer->cert_l = cert_l; peer->cert_k = cert_k; peer->iddata_r = iddata_r; peer->iddata_l = iddata_l; psk.del(); cert_l.del(); cert_k.del(); iddata_r.del(); iddata_l.del(); IKE_PROPOSAL * proposal; long index = 0; while( proposals.get( &proposal, index++ ) ) peer->proposals.add( proposal, true ); if( !peer->add( true ) ) { log.txt( LLOG_ERROR, "!! : unable to add peer object\n" ); detach = true; delete peer; peer = NULL; break; } // // determine local tunnel addresses // if( socket_lookup_addr( peer->saddr, saddr_l ) != LIBIKE_OK ) { log.txt( LLOG_ERROR, "!! : no route to host\n" ); detach = true; break; } // // determine local socket port // if( socket_lookup_port( saddr_l, false ) != LIBIKE_OK ) { log.txt( LLOG_ERROR, "!! : no socket for selected address\n" ); detach = true; break; } // // create tunnel object // tunnel = new IDB_TUNNEL( peer, &ike_xconf, &saddr_l, &peer->saddr ); if( tunnel == NULL ) { log.txt( LLOG_ERROR, "!! : unable to create tunnel object\n" ); detach = true; break; } tunnel->ikei = ikei; tunnel->xauth.user = xuser; tunnel->xauth.pass = xpass; xuser.del( true ); xpass.del( true ); IKE_PH2ID ph2id; index = 0; while( idlist_incl.get( ph2id, index++ ) ) tunnel->idlist_incl.add( ph2id ); index = 0; while( idlist_excl.get( ph2id, index++ ) ) tunnel->idlist_excl.add( ph2id ); BDATA domain; index = 0; while( domains.get( domain, index++ ) ) tunnel->domains.add( domain ); domain.del(); if( !tunnel->add( true ) ) { log.txt( LLOG_ERROR, "!! : unable to add tunnel object\n" ); detach = true; delete tunnel; tunnel = NULL; break; } // // initiate communications with peer // IDB_PH1 * ph1 = new IDB_PH1( tunnel, true, NULL ); ph1->add( true ); process_phase1_send( ph1 ); ph1->dec( true ); msg.set_status( STATUS_CONNECTING, "tunnel connecting ...\n" ); ikei->send_message( msg ); } else { log.txt( LLOG_INFO, "close = XCH_FAILED_USERREQ; msg.set_status( STATUS_DISCONNECTING, "tunnel disconnecting ...\n" ); ikei->send_message( msg ); } break; } #ifdef WIN32 // // suspend tunnel message // case IKEI_MSGID_SUSPEND: { long suspend = 0; if( msg.get_suspend( &suspend ) != IPCERR_OK ) { log.txt( LLOG_ERROR, "!! : failed to read tunnel suspend message\n" ); break; } if( suspend ) { iked.ith_timer.del( &tunnel->event_stats ); log.txt( LLOG_DEBUG, "ii : suspended client control of tunnel\n" ); tunnel->suspended = true; tunnel->ikei = NULL; tunnel->dec( true ); suspended = true; detach = true; } else { if( !iked.idb_list_tunnel.find( true, &tunnel, NULL, NULL, false, true ) ) { log.txt( LLOG_ERROR, "!! : failed to locate suspended tunnel\n" ); detach = true; break; } log.txt( LLOG_DEBUG, "ii : resumed client control of tunnel\n" ); peer = tunnel->peer; tunnel->suspended = false; tunnel->ikei = ikei; ith_timer.add( &tunnel->event_stats ); } break; } #endif default: log.txt( LLOG_ERROR, "!! : message type is invalid ( %u )\n", msg.header.type ); if( tunnel != NULL ) tunnel->close = XCH_FAILED_CLIENT; break; } // // send result message // msg.set_result( result ); ikei->send_message( msg ); continue; } // // tunnel configuration steps ( IPCERR_WAKEUP ) // if( tunnel != NULL ) { // // start client receive thread when ready // if( !( tunnel->close ) && ( tunnel->tstate & TSTATE_VNET_CONFIG ) && !( tunnel->tstate & TSTATE_VNET_ENABLE ) ) { // // if there is a banner, show it now // if( tunnel->banner.size() ) { msg.set_status( STATUS_BANNER, &tunnel->banner ); ikei->send_message( msg ); } // // make sure we have a valid vnet // address and netmask // if( !tunnel->xconf.addr.s_addr ) { log.txt( LLOG_ERROR, "!! : invalid private address\n" ); tunnel->close = XCH_FAILED_ADAPTER; break; } if( !tunnel->xconf.mask.s_addr ) { log.txt( LLOG_ERROR, "!! : invalid private netmask, defaulting to 255.255.255.0\n" ); tunnel->xconf.mask.s_addr = inet_addr( "255.255.255.0" ); } // // setup client network parameters // if( !client_net_config( tunnel ) ) break; msg.set_status( STATUS_INFO, "network device configured\n" ); ikei->send_message( msg ); // // generate a policy list now // policy_list_create( tunnel, true ); // // setup client dns parameters // client_dns_config( tunnel ); // // tunnel is enabled // msg.set_status( STATUS_CONNECTED, "tunnel connected\n" ); ikei->send_message( msg ); // // add the statistics event // tunnel->inc( true ); tunnel->event_stats.delay = 1000; ith_timer.add( &tunnel->event_stats ); tunnel->tstate |= TSTATE_VNET_ENABLE; } } } // // perform tunnel cleanup // if( tunnel == NULL ) { // // tunnel configuration failed // msg.set_status( STATUS_FAIL, "tunnel configuration failed\n" ); ikei->send_message( msg ); } if( ( tunnel != NULL ) && !suspended ) { // // revert client network parameters // client_dns_revert( tunnel ); // // cleanup client settings // // NOTE : policy cleanup must be done here to // avoid route deletion failures from occuring // after a virtual adapter has been removed // lock_idb.lock(); if( tunnel->peer->plcy_mode != POLICY_MODE_DISABLE ) iked.policy_list_remove( tunnel, true ); lock_idb.unlock(); if( tunnel->peer->xconf_mode == CONFIG_MODE_DHCP ) iked.socket_dhcp_remove( tunnel ); // // revert client network parameters // client_net_revert( tunnel ); // // flush our arp cache // iproute.flusharp( saddr_l.saddr4.sin_addr ); // // report reason for closing the tunnel // switch( tunnel->close ) { // // client message error // case XCH_FAILED_CLIENT: msg.set_status( STATUS_FAIL, "client configuration error\n" ); break; // // network communication error // case XCH_FAILED_NETWORK: msg.set_status( STATUS_FAIL, "network unavailable\n" ); break; // // adapter configuration error // case XCH_FAILED_ADAPTER: msg.set_status( STATUS_FAIL, "adapter configuration failed\n" ); break; // // network timeout occurred // case XCH_FAILED_TIMEOUT: msg.set_status( STATUS_FAIL, "negotiation timout occurred\n" ); break; // // terminated by user // case XCH_FAILED_USERREQ: msg.set_status( STATUS_WARN, "session terminated by user\n" ); break; // // an invalid message was received // case XCH_FAILED_MSG_FORMAT: case XCH_FAILED_MSG_CRYPTO: case XCH_FAILED_MSG_AUTH: msg.set_status( STATUS_FAIL, "invalid message from gateway\n" ); break; // // user authentication error // case XCH_FAILED_USER_AUTH: msg.set_status( STATUS_FAIL, "user authentication error\n" ); break; // // peer authentication error // case XCH_FAILED_PEER_AUTH: msg.set_status( STATUS_FAIL, "gateway authentication error\n" ); break; // // peer unresponsive // case XCH_FAILED_PEER_DEAD: msg.set_status( STATUS_FAIL, "gateway is not responding\n" ); break; // // terminated by peer // case XCH_FAILED_PEER_DELETE: msg.set_status( STATUS_FAIL, "session terminated by gateway\n" ); break; // // dhcp unresponsive // case XCH_FAILED_IKECONFIG: msg.set_status( STATUS_FAIL, "no config response from gateway\n" ); break; // // dhcp unresponsive // case XCH_FAILED_DHCPCONFIG: msg.set_status( STATUS_FAIL, "no dhcp response from gateway\n" ); break; // // unknown // default: msg.set_status( STATUS_FAIL, "internal error occurred\n" ); break; } ikei->send_message( msg ); // // release the tunnel object // tunnel->dec( true, true ); msg.set_status( STATUS_DISCONNECTED, "tunnel disconnected\n" ); } // // perform peer cleanup // if( ( peer != NULL ) && !suspended ) { peer->dec( true, true ); msg.set_status( STATUS_DISCONNECTED, "peer removed\n" ); } // // close the client interface // ikei->send_message( msg ); ikei->detach(); delete ikei; // // flush our private pcap dump files // if( dump_decrypt ) pcap_decrypt.flush(); loop_ref_dec( "ipc client" ); return true; } ike-2.2.1+dfsg/source/iked/ike.io.network.cpp000066400000000000000000000266671223036517100210120ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "iked.h" // // ike network io thread // long ITH_NWORK::iked_func( void * arg ) { IKED * iked = ( IKED * ) arg; return iked->loop_ike_nwork(); } long _IKED::loop_ike_nwork() { // // begin network thread // loop_ref_inc( "network" ); ETH_HEADER eth_header; PACKET_IP packet_ip; while( true ) { // // attempt to recv packet // long result = recv_ip( packet_ip, ð_header ); if( result == LIBIKE_SOCKET ) break; if( result == LIBIKE_NODATA ) continue; // // dump encrypted packets // if( dump_encrypt ) pcap_encrypt.dump( eth_header, packet_ip ); // // read the ip header // IKE_SADDR saddr_src; IKE_SADDR saddr_dst; memset( &saddr_src, 0, sizeof( saddr_src ) ); memset( &saddr_dst, 0, sizeof( saddr_dst ) ); saddr_src.saddr4.sin_family = AF_INET; saddr_dst.saddr4.sin_family = AF_INET; unsigned char proto; packet_ip.read( saddr_src.saddr4.sin_addr, saddr_dst.saddr4.sin_addr, proto ); // // convert source ip address // to a string for logging // char txtaddr_src[ LIBIKE_MAX_TEXTADDR ]; char txtaddr_dst[ LIBIKE_MAX_TEXTADDR ]; text_addr( txtaddr_src, &saddr_src, false ); text_addr( txtaddr_dst, &saddr_dst, false ); // // is this a UDP packet // if( proto == PROTO_IP_UDP ) { // // read the udp packet // PACKET_UDP packet_udp; packet_ip.get( packet_udp ); packet_udp.read( saddr_src.saddr4.sin_port, saddr_dst.saddr4.sin_port ); unsigned short port_src = htons( saddr_src.saddr4.sin_port ); unsigned short port_dst = htons( saddr_dst.saddr4.sin_port ); // // check for NAT-T keep alive // if( packet_udp.size() < sizeof( IKE_HEADER ) ) { log.txt( LLOG_DEBUG, "<- : recv NAT-T:KEEP-ALIVE packet %s:%u -> %s:%u\n", txtaddr_src, port_src, txtaddr_dst, port_dst ); continue; } // // examine the packet contents // for a NAT-T non-ESP marker // uint32_t * marker = ( uint32_t * )( packet_udp.buff() + packet_udp.oset() ); if( marker[ 0 ] ) { // // obtain packet payload // PACKET_IKE packet_ike; packet_udp.get( packet_ike ); log.bin( LLOG_DEBUG, LLOG_DECODE, packet_ike.buff(), packet_ike.size(), "<- : recv IKE packet %s:%u -> %s:%u", txtaddr_src, port_src, txtaddr_dst, port_dst ); // // process the ike packet // process_ike_recv( packet_ike, saddr_src, saddr_dst ); continue; } else { // // skip the null marker // packet_udp.get_null( 4 ); // // obtain IKE packet payload // PACKET_IKE packet_ike; packet_udp.get( packet_ike ); // // process the ike packet // log.bin( LLOG_DEBUG, LLOG_DECODE, packet_ike.buff(), packet_ike.size(), "<- : recv NAT-T:IKE packet %s:%u -> %s:%u", txtaddr_src, port_src, txtaddr_dst, port_dst ); process_ike_recv( packet_ike, saddr_src, saddr_dst ); } } } loop_ref_dec( "network" ); return LIBIKE_OK; } long _IKED::process_ike_recv( PACKET_IKE & packet, IKE_SADDR & saddr_src, IKE_SADDR & saddr_dst ) { // // read packet header // IKE_COOKIES cookies; uint8_t payload; uint8_t exchange; uint8_t flags; if( !packet.read( cookies, payload, exchange, flags ) ) { log.txt( LLOG_ERROR, "!! : invalid ISAKMP header\n" ); return LIBIKE_OK; } char txtaddr_src[ LIBIKE_MAX_TEXTADDR ]; text_addr( txtaddr_src, &saddr_src, false ); // // attempt to locate a known sa // sa for this packet // IDB_PH1 * ph1 = NULL; if( !idb_list_ph1.find( true, &ph1, NULL, XCH_STATUS_ANY, XCH_STATUS_ANY, &cookies ) ) { // // if we are acting as a responder // and the packet has an SA as its // first payload as well as a null // value for the responder cookie // bool null_cookie = true; for( long x = 0; x < ISAKMP_COOKIE_SIZE; x++ ) { if( cookies.r[ x ] ) { null_cookie = false; break; } } if( !null_cookie ) { log.txt( LLOG_INFO, "ww : ike packet from %s ignored, unknown phase1 sa for peer\n" "ww : %08x%08x:%08x%08x\n", txtaddr_src, htonl( *( long * ) &cookies.i[ 0 ] ), htonl( *( long * ) &cookies.i[ 4 ] ), htonl( *( long * ) &cookies.r[ 0 ] ), htonl( *( long * ) &cookies.r[ 4 ] ) ); return LIBIKE_OK; } // // attempt to locate a tunnel // definition for this peer // log.txt( LLOG_DEBUG, "ii : attempting to locate tunnel for peer %s\n", txtaddr_src ); IDB_TUNNEL * tunnel = NULL; if( !idb_list_tunnel.find( true, &tunnel, NULL, &saddr_src, true, false ) ) { // // attempt to locate a peer // configuration by address // IDB_PEER * peer; if( !idb_list_peer.find( true, &peer, &saddr_src ) ) { log.txt( LLOG_INFO, "ww : ike packet from %s ignored, no matching definition for peer\n", txtaddr_src ); return LIBIKE_OK; } tunnel = new IDB_TUNNEL( peer, NULL, &saddr_dst, &saddr_src ); if( tunnel == NULL ) { log.txt( LLOG_INFO, "ww : ike packet from %s ignored, unable to create tunnel object\n", txtaddr_src ); peer->dec( true ); return LIBIKE_MEMORY; } tunnel->add( true ); peer->dec( true ); } // // verify that the exchange type is correct // and that we allow contact from this peer // if( exchange != tunnel->peer->exchange ) { log.txt( LLOG_INFO, "ww : ike packet from %s ignored, exchange type mismatch for peer\n", txtaddr_src ); tunnel->dec( true ); return LIBIKE_OK; } if( ( tunnel->peer->contact != IPSEC_CONTACT_RESP ) && ( tunnel->peer->contact != IPSEC_CONTACT_BOTH ) ) { log.txt( LLOG_INFO, "ww : ike packet from %s ignored, contact is denied for peer\n", txtaddr_src ); tunnel->dec( true ); return LIBIKE_OK; } if( packet.get_msgid() ) { log.txt( LLOG_INFO, "ww : ike packet from %s ignored, invalid message id for exchange type\n", txtaddr_src ); tunnel->dec( true ); return LIBIKE_OK; } // // looks like a valid initial contact attempt. // allocate a new SA // log.txt( LLOG_DEBUG, "ii : creating new phase1 handle for peer %s\n", txtaddr_src ); ph1 = new IDB_PH1( tunnel, false, &cookies ); if( ph1 == NULL ) { log.txt( LLOG_INFO, "ww : ike packet from %s ignored, unable to create phase1 handle\n", txtaddr_src ); tunnel->dec( true ); return LIBIKE_MEMORY; } ph1->add( true ); tunnel->dec( true ); } // // check the remote port value against // the recorded tunnel port value // if( !phase1_chk_port( ph1, &saddr_src, &saddr_dst ) ) { ph1->dec( true ); return LIBIKE_FAILED; } // // handle fragmented ike packets // if( payload == ISAKMP_PAYLOAD_FRAGMENT ) { // // if fragmentation was not negotiated // then dump the packet // if( !ph1->vendopts_l.flag.frag ) { log.txt( LLOG_ERROR, "!! : fragmented packet received but local support is disabled\n" ); ph1->dec( true ); return LIBIKE_FAILED; } // // process the ike fragment payload // bool complete = false; long result = payload_get_frag( packet, ph1, complete ); if( result != LIBIKE_OK ) { log.txt( LLOG_ERROR, "!! : unable to process ike fragment payload\n" ); ph1->dec( true ); return result; } // // if this was the last ike fragment, // the packet data should now have // been replaced with a complete packet. // otherwise we have nothing more to do // if( !complete ) { log.txt( LLOG_INFO, "ii : ike fragment received, waiting on complete packet\n" ); ph1->dec( true ); return LIBIKE_OK; } // // we have a complete packet, read the // complete packets header and proceed // packet.read( cookies, payload, exchange, flags ); log.txt( LLOG_INFO, "ii : ike fragment received, processing complete packet\n" ); } // // process packet based on exchange type // long result = LIBIKE_OK; switch( exchange ) { // // phase1 exchange // case ISAKMP_EXCH_IDENT_PROTECT: case ISAKMP_EXCH_AGGRESSIVE: result = process_phase1_recv( ph1, packet, payload ); break; // // phase2 exchange // case ISAKMP_EXCH_QUICK: result = process_phase2_recv( ph1, packet, payload ); break; // // informational exchange // case ISAKMP_EXCH_INFORMATIONAL: result = process_inform_recv( ph1, packet, payload ); break; // // transactional config exchange // case ISAKMP_EXCH_CONFIG: result = process_config_recv( ph1, packet, payload ); break; // // unknown exchange // default: { log.txt( LLOG_ERROR, "!! : unhandled exchange type %s ( %i )\n", find_name( NAME_EXCHANGE, exchange ), exchange ); result = LIBIKE_OK; break; } } ph1->dec( true ); return result; } long _IKED::process_ike_send() { return LIBIKE_OK; } ike-2.2.1+dfsg/source/iked/ike.io.pfkey.cpp000066400000000000000000001263611223036517100204270ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "iked.h" // // ike pfkey io thread // long ITH_PFKEY::iked_func( void * arg ) { IKED * iked = ( IKED * ) arg; return iked->loop_ike_pfkey(); } long _IKED::loop_ike_pfkey() { // // begin pfkey thread // loop_ref_inc( "pfkey" ); PFKI_MSG msg; while( true ) { // // read the next pfkey message // long result = pfki.recv_message( msg ); if( result == IPCERR_WAKEUP ) break; if( result == IPCERR_CLOSED ) { pfki.detach(); if( pfki.attach( 1000 ) != IPCERR_OK ) { log.txt( LLOG_ERROR, "!! : unable to connect to pfkey interface\n" ); Sleep( 1000 ); continue; } // // register for certain protocol types // if( ( pfki.send_register( SADB_SATYPE_AH ) != IPCERR_OK ) || ( pfki.send_register( SADB_SATYPE_ESP ) != IPCERR_OK ) || ( pfki.send_register( SADB_X_SATYPE_IPCOMP ) != IPCERR_OK ) ) { log.txt( LLOG_ERROR, "!! : unable to send pfkey register message\n" ); return LIBIKE_FAILED; } // // initiate an SPD dump // if( pfki.send_spdump() != IPCERR_OK ) { log.txt( LLOG_ERROR, "!! : unable to send pfkey spd dump message\n" ); return LIBIKE_FAILED; } continue; } if( result != IPCERR_OK ) continue; if( msg.header.sadb_msg_errno ) { log.txt( LLOG_ERROR, "K! : recv %s message failure ( errno = %i )\n", pfki.name( NAME_MSGTYPE, msg.header.sadb_msg_type ), msg.header.sadb_msg_errno ); continue; } // // process the message by type // switch( msg.header.sadb_msg_type ) { case SADB_REGISTER: if( msg.local() ) log.txt( LLOG_DEBUG, "K< : recv pfkey %s %s message\n", pfki.name( NAME_MSGTYPE, msg.header.sadb_msg_type ), pfki.name( NAME_SATYPE, msg.header.sadb_msg_satype ) ); else log.txt( LLOG_DEBUG, "K< : recv pfkey %s %s message ( ignored )\n", pfki.name( NAME_MSGTYPE, msg.header.sadb_msg_type ), pfki.name( NAME_SATYPE, msg.header.sadb_msg_satype ) ); break; case SADB_FLUSH: log.txt( LLOG_DEBUG, "K< : recv pfkey %s %s message\n", pfki.name( NAME_MSGTYPE, msg.header.sadb_msg_type ), pfki.name( NAME_SATYPE, msg.header.sadb_msg_satype ) ); pfkey_recv_flush( msg ); break; case SADB_ACQUIRE: log.txt( LLOG_DEBUG, "K< : recv pfkey %s %s message\n", pfki.name( NAME_MSGTYPE, msg.header.sadb_msg_type ), pfki.name( NAME_SATYPE, msg.header.sadb_msg_satype ) ); pfkey_recv_acquire( msg ); break; case SADB_GETSPI: log.txt( LLOG_DEBUG, "K< : recv pfkey %s %s message\n", pfki.name( NAME_MSGTYPE, msg.header.sadb_msg_type ), pfki.name( NAME_SATYPE, msg.header.sadb_msg_satype ) ); pfkey_recv_getspi( msg ); break; case SADB_UPDATE: log.txt( LLOG_DEBUG, "K< : recv pfkey %s %s message\n", pfki.name( NAME_MSGTYPE, msg.header.sadb_msg_type ), pfki.name( NAME_SATYPE, msg.header.sadb_msg_satype ) ); break; case SADB_DELETE: log.txt( LLOG_DEBUG, "K< : recv pfkey %s %s message\n", pfki.name( NAME_MSGTYPE, msg.header.sadb_msg_type ), pfki.name( NAME_SATYPE, msg.header.sadb_msg_satype ) ); break; case SADB_X_SPDFLUSH: log.txt( LLOG_DEBUG, "K< : recv pfkey %s %s message\n", pfki.name( NAME_MSGTYPE, msg.header.sadb_msg_type ), pfki.name( NAME_SATYPE, msg.header.sadb_msg_satype ) ); pfkey_recv_spflush( msg ); break; case SADB_X_SPDADD: case SADB_X_SPDGET: log.txt( LLOG_DEBUG, "K< : recv pfkey %s %s message\n", pfki.name( NAME_MSGTYPE, msg.header.sadb_msg_type ), pfki.name( NAME_SATYPE, msg.header.sadb_msg_satype ) ); pfkey_recv_spadd( msg ); break; case SADB_X_SPDDUMP: log.txt( LLOG_DEBUG, "K< : recv pfkey %s %s message\n", pfki.name( NAME_MSGTYPE, msg.header.sadb_msg_type ), pfki.name( NAME_SATYPE, msg.header.sadb_msg_satype ) ); pfkey_recv_spnew( msg ); break; case SADB_X_SPDDELETE2: log.txt( LLOG_DEBUG, "K< : recv pfkey %s %s message\n", pfki.name( NAME_MSGTYPE, msg.header.sadb_msg_type ), pfki.name( NAME_SATYPE, msg.header.sadb_msg_satype ) ); pfkey_recv_spdel( msg ); break; default: log.txt( LLOG_ERROR, "K! : unhandled pfkey message type %s ( %i )\n", pfki.name( NAME_MSGTYPE, msg.header.sadb_msg_type ), msg.header.sadb_msg_type ); break; } } pfki.detach(); loop_ref_dec( "pfkey" ); return LIBIKE_OK; } bool _IKED::paddr_ph2id( PFKI_ADDR & paddr, IKE_PH2ID & ph2id ) { switch( paddr.saddr.sa_family ) { case AF_INET: { if( paddr.proto != IPSEC_PROTO_ANY ) ph2id.prot = paddr.proto; else ph2id.prot = 0; ph2id.port = paddr.saddr4.sin_port; ph2id.type = ISAKMP_ID_IPV4_ADDR; ph2id.addr1 = paddr.saddr4.sin_addr; ph2id.addr2.s_addr = 0; if( paddr.prefix < 32 ) { ph2id.type = ISAKMP_ID_IPV4_ADDR_SUBNET; for( long i = 0; i < paddr.prefix; i++ ) { ph2id.addr2.s_addr >>= 1; ph2id.addr2.s_addr |= 0x80000000; } ph2id.addr2.s_addr = htonl( ph2id.addr2.s_addr ); } return true; } default: log.txt( LLOG_ERROR, "!! : ph2id -> pfkiaddr, unhandled address faimily %i\n", paddr.saddr.sa_family ); } return false; } bool _IKED::ph2id_paddr( IKE_PH2ID & ph2id, PFKI_ADDR & paddr ) { switch( ph2id.type ) { case ISAKMP_ID_IPV4_ADDR: case ISAKMP_ID_IPV4_ADDR_SUBNET: { paddr.saddr4.sin_family = AF_INET; SET_SALEN( &paddr.saddr4, sizeof( sockaddr_in ) ); paddr.saddr4.sin_addr = ph2id.addr1; paddr.saddr4.sin_port = ph2id.port; if( ph2id.prot ) paddr.proto = ph2id.prot; else paddr.proto = IPSEC_PROTO_ANY; if( ph2id.type == ISAKMP_ID_IPV4_ADDR ) paddr.prefix = 32; else { unsigned long mask = ntohl( ph2id.addr2.s_addr ); while( mask & 0x80000000 ) { mask <<= 1; paddr.prefix++; } } return true; } default: log.txt( LLOG_ERROR, "!! : ph2id -> pfkiaddr, unhandled id type %i\n", ph2id.type ); } return false; } long _IKED::pfkey_init_phase2( bool nail, u_int16_t plcytype, u_int32_t plcyid, u_int32_t seq ) { // // locate oubound policy by id // IDB_POLICY * policy_out; if( !idb_list_policy.find( true, &policy_out, IPSEC_DIR_OUTBOUND, plcytype, NULL, &plcyid, NULL, NULL, NULL, NULL ) ) { log.txt( LLOG_ERROR, "!! : unable to locate outbound policy for init phase2\n" ); return LIBIKE_FAILED; } // // if this policy was marked as // nailed for a client tunnel, // ignore the request if it came // in the form of an aquire // if( ( policy_out->flags & PFLAG_NAILED ) && !nail ) { log.txt( LLOG_INFO, "ii : ignoring init phase2 by acquire, tunnel is nailed\n" ); return LIBIKE_FAILED; } // // locate inbound policy by the // source and destination addrs // and ids // IKE_SADDR src, dst; policy_get_addrs( policy_out, src, dst ); IKE_PH2ID ids, idd; paddr_ph2id( policy_out->paddr_src, ids ); paddr_ph2id( policy_out->paddr_dst, idd ); IDB_POLICY * policy_in; if( !idb_list_policy.find( true, &policy_in, IPSEC_DIR_INBOUND, plcytype, NULL, NULL, &dst, &src, &idd, &ids ) ) { log.txt( LLOG_ERROR, "!! : unable to locate inbound policy for init phase2\n" ); policy_out->dec( true ); return LIBIKE_FAILED; } // // attempt to locate an existing // tunnel for the policy // IDB_TUNNEL * tunnel; if( !idb_list_tunnel.find( true, &tunnel, NULL, &dst, false, false ) ) { // // attempt to locate an existing // peer config for the policy // IDB_PEER * peer; if( !idb_list_peer.find( true, &peer, &dst ) ) { log.txt( LLOG_ERROR, "!! : unable to locate peer config for policy\n" ); policy_in->dec( true ); policy_out->dec( true ); return LIBIKE_FAILED; } // // attempt to locate the socket // for our address and the ike // port value // if( socket_lookup_port( src, false ) != LIBIKE_OK ) { char txtaddr[ LIBIKE_MAX_TEXTADDR ]; text_addr( txtaddr, &src, true ); log.txt( LLOG_ERROR, "!! : unable to create tunnel, no socket for address %s\n", txtaddr ); policy_in->dec( true ); policy_out->dec( true ); return LIBIKE_FAILED; } // // attempt to create and add a new // tunnel for the peer // tunnel = new IDB_TUNNEL( peer, NULL, &src, &peer->saddr ); if( tunnel == NULL ) { log.txt( LLOG_ERROR, "!! : unable to create new tunnel object\n" ); peer->dec( true ); policy_in->dec( true ); policy_out->dec( true ); return LIBIKE_FAILED; } if( !tunnel->add( true ) ) { log.txt( LLOG_ERROR, "!! : unable to add tunnel object\n" ); delete tunnel; peer->dec( true ); policy_in->dec( true ); policy_out->dec( true ); return LIBIKE_FAILED; } peer->dec( true ); } // // create a new phase2 handler // for the security association // IDB_PH2 * ph2 = new IDB_PH2( tunnel, true, 0, seq ); if( ph2 == NULL ) { tunnel->dec( true ); policy_in->dec( true ); policy_out->dec( true ); return LIBIKE_FAILED; } if( !ph2->add( true ) != LIBIKE_OK ) { delete ph2; tunnel->dec( true ); policy_in->dec( true ); policy_out->dec( true ); return LIBIKE_FAILED; } // // store the policy ids // ph2->plcyid_in = policy_in->sp.id; ph2->plcyid_out = policy_out->sp.id; // // store the nailed sa option // ph2->nailed = nail; // // if the tunnel uses shared policy level, we // use a remote ID of 0.0.0.0/0 regardless of // the sa ID value // if( tunnel->peer->plcy_level == POLICY_LEVEL_SHARED ) { idd.addr1.s_addr = 0; idd.addr2.s_addr = 0; } // // configure the phase2 network ids // ph2->ph2id_ls = ids; ph2->ph2id_ld = idd; // // configure the phase2 proposal list // phase2_gen_prop( ph2, policy_out ); // // configure the phase2 dh group // ph2->setup_dhgrp(); // // acquire any needed pfkey spis // pfkey_send_getspi( policy_in, ph2 ); // // cleanup // ph2->dec( true ); tunnel->dec( true ); policy_in->dec( true ); policy_out->dec( true ); return LIBIKE_OK; } long _IKED::pfkey_recv_spadd( PFKI_MSG & msg ) { PFKI_SPINFO spinfo; memset( &spinfo, 0, sizeof( spinfo ) ); if( pfki.read_policy( msg, spinfo ) != IPCERR_OK ) { log.txt( LLOG_ERROR, "K! : failed to read basic policy info\n" ); return LIBIKE_FAILED; } if( ( pfki.read_address_src( msg, spinfo.paddr_src ) != IPCERR_OK ) || ( pfki.read_address_dst( msg, spinfo.paddr_dst ) != IPCERR_OK ) ) { log.txt( LLOG_ERROR, "K! : failed to read policy address info\n" ); return LIBIKE_FAILED; } char txtid_src[ LIBIKE_MAX_TEXTP2ID ]; char txtid_dst[ LIBIKE_MAX_TEXTP2ID ]; text_addr( txtid_src, &spinfo.paddr_src, true, true ); text_addr( txtid_dst, &spinfo.paddr_dst, true, true ); log.txt( LLOG_DECODE, "ii : - id = %i\n" "ii : - type = %s\n" "ii : - dir = %s\n" "ii : - src = %s\n" "ii : - dst = %s\n", spinfo.sp.id, pfki.name( NAME_SPTYPE, spinfo.sp.type ), pfki.name( NAME_SPDIR, spinfo.sp.dir ), txtid_src, txtid_dst ); if( spinfo.sp.type == IPSEC_POLICY_IPSEC ) { for( long xindex = 0; xindex < PFKI_MAX_XFORMS; xindex++ ) { if( !spinfo.xforms[ xindex ].proto ) { if( xindex ) break; log.txt( LLOG_ERROR, "!! : failed to add policy, no transforms defind\n" ); return LIBIKE_FAILED; } char txtaddr_src[ LIBIKE_MAX_TEXTADDR ]; char txtaddr_dst[ LIBIKE_MAX_TEXTADDR ]; text_addr( txtaddr_src, &spinfo.xforms[ xindex ].saddr_src, false ); text_addr( txtaddr_dst, &spinfo.xforms[ xindex ].saddr_dst, false ); log.txt( LLOG_DECODE, "ii : - transform #%i\n" "ii : -- proto = %i\n" "ii : -- level = %s\n" "ii : -- mode = %s\n" "ii : -- reqid = %i\n" "ii : -- tsrc = %s\n" "ii : -- tdst = %s\n", xindex, spinfo.xforms[ xindex ].proto, pfki.name( NAME_SPLEVEL, spinfo.xforms[ xindex ].level ), pfki.name( NAME_SPMODE, spinfo.xforms[ xindex ].mode ), spinfo.xforms[ xindex ].reqid, txtaddr_src, txtaddr_dst ); } } // // locate policy // IDB_POLICY * policy; if( !idb_list_policy.find( true, &policy, spinfo.sp.dir, spinfo.sp.type, &msg.header.sadb_msg_seq, NULL, NULL, NULL, NULL, NULL ) ) { log.txt( LLOG_ERROR, "!! : unable to locate policy with sequence 0x%08x\n", spinfo.seq ); return LIBIKE_FAILED; } // // update the policy id // policy->sp.id = spinfo.sp.id; // // if this policy was marked as nailed // or initial for a client tunnel, call // init phase2 now // if( policy->flags & PFLAG_NAILED ) { log.txt( LLOG_DEBUG, "ii : calling init phase2 for nailed policy\n" ); pfkey_init_phase2( true, spinfo.sp.type, spinfo.sp.id, 0 ); } if( policy->flags & PFLAG_INITIAL ) { policy->flags &= ~PFLAG_INITIAL; log.txt( LLOG_DEBUG, "ii : calling init phase2 for initial policy\n" ); pfkey_init_phase2( true, spinfo.sp.type, spinfo.sp.id, 0 ); } policy->dec( true ); return LIBIKE_OK; } long _IKED::pfkey_recv_spnew( PFKI_MSG & msg ) { PFKI_SPINFO spinfo; memset( &spinfo, 0, sizeof( spinfo ) ); if( pfki.read_policy( msg, spinfo ) != IPCERR_OK ) { log.txt( LLOG_ERROR, "K! : failed to read basic policy info\n" ); return LIBIKE_FAILED; } if( ( pfki.read_address_src( msg, spinfo.paddr_src ) != IPCERR_OK ) || ( pfki.read_address_dst( msg, spinfo.paddr_dst ) != IPCERR_OK ) ) { log.txt( LLOG_ERROR, "K! : failed to read policy address info\n" ); return LIBIKE_FAILED; } char txtid_src[ LIBIKE_MAX_TEXTP2ID ]; char txtid_dst[ LIBIKE_MAX_TEXTP2ID ]; text_addr( txtid_src, &spinfo.paddr_src, true, true ); text_addr( txtid_dst, &spinfo.paddr_dst, true, true ); log.txt( LLOG_DECODE, "ii : - id = %i\n" "ii : - type = %s\n" "ii : - dir = %s\n" "ii : - src = %s\n" "ii : - dst = %s\n", spinfo.sp.id, pfki.name( NAME_SPTYPE, spinfo.sp.type ), pfki.name( NAME_SPDIR, spinfo.sp.dir ), txtid_src, txtid_dst ); if( spinfo.sp.type == IPSEC_POLICY_IPSEC ) { for( long xindex = 0; xindex < PFKI_MAX_XFORMS; xindex++ ) { if( !spinfo.xforms[ xindex ].proto ) { if( xindex ) break; log.txt( LLOG_ERROR, "!! : failed to add policy, no transforms defind\n" ); return LIBIKE_FAILED; } char txtaddr_src[ LIBIKE_MAX_TEXTADDR ]; char txtaddr_dst[ LIBIKE_MAX_TEXTADDR ]; text_addr( txtaddr_src, &spinfo.xforms[ xindex ].saddr_src, false ); text_addr( txtaddr_dst, &spinfo.xforms[ xindex ].saddr_dst, false ); log.txt( LLOG_DECODE, "ii : - transform #%i\n" "ii : -- proto = %i\n" "ii : -- level = %s\n" "ii : -- mode = %s\n" "ii : -- reqid = %i\n" "ii : -- tsrc = %s\n" "ii : -- tdst = %s\n", xindex, spinfo.xforms[ xindex ].proto, pfki.name( NAME_SPLEVEL, spinfo.xforms[ xindex ].level ), pfki.name( NAME_SPMODE, spinfo.xforms[ xindex ].mode ), spinfo.xforms[ xindex ].reqid, txtaddr_src, txtaddr_dst ); } } // // create a local policy entry // IDB_POLICY * policy = new IDB_POLICY( &spinfo ); if( policy == NULL ) return LIBIKE_FAILED; // // add the policy and cleanup // policy->add( true ); policy->dec( true ); return LIBIKE_OK; } long _IKED::pfkey_recv_acquire( PFKI_MSG & msg ) { PFKI_SPINFO spinfo; memset( &spinfo, 0, sizeof( spinfo ) ); if( pfki.read_policy( msg, spinfo ) != IPCERR_OK ) { log.txt( LLOG_ERROR, "K! : failed to read basic policy info\n" ); return LIBIKE_FAILED; } if( spinfo.sp.type != IPSEC_POLICY_IPSEC ) { log.txt( LLOG_DECODE, "ii : - id = %i\n" "ii : - type = %s\n" "ii : - dir = %s\n", spinfo.sp.id, pfki.name( NAME_SPTYPE, spinfo.sp.type ), pfki.name( NAME_SPDIR, spinfo.sp.dir ) ); return LIBIKE_OK; } if( ( pfki.read_address_src( msg, spinfo.paddr_src ) != IPCERR_OK ) || ( pfki.read_address_dst( msg, spinfo.paddr_dst ) != IPCERR_OK ) ) { log.txt( LLOG_ERROR, "K! : failed to read policy address info\n" ); return LIBIKE_FAILED; } char txtid_src[ LIBIKE_MAX_TEXTP2ID ]; char txtid_dst[ LIBIKE_MAX_TEXTP2ID ]; text_addr( txtid_src, &spinfo.paddr_src, true, true ); text_addr( txtid_dst, &spinfo.paddr_dst, true, true ); log.txt( LLOG_DECODE, "ii : - id = %i\n" "ii : - type = %s\n" "ii : - dir = %s\n" "ii : - src = %s\n" "ii : - dst = %s\n", spinfo.sp.id, pfki.name( NAME_SPTYPE, spinfo.sp.type ), pfki.name( NAME_SPDIR, spinfo.sp.dir ), txtid_src, txtid_dst ); // // initiate phase2 based on the aquire info // return pfkey_init_phase2( false, spinfo.sp.type, spinfo.sp.id, msg.header.sadb_msg_seq ); } long _IKED::pfkey_recv_getspi( PFKI_MSG & msg ) { if( !msg.local() ) { log.txt( LLOG_DECODE, "ii : - message ignored ( not local )\n" ); return LIBIKE_OK; } PFKI_SA sa; memset( &sa, 0, sizeof( sa ) ); if( pfki.read_sa( msg, sa ) != IPCERR_OK ) { log.txt( LLOG_ERROR, "K! : failed to read security association info\n" ); return LIBIKE_FAILED; } PFKI_ADDR paddr_src; PFKI_ADDR paddr_dst; if( ( pfki.read_address_src( msg, paddr_src ) != IPCERR_OK ) || ( pfki.read_address_dst( msg, paddr_dst ) != IPCERR_OK ) ) { log.txt( LLOG_ERROR, "K! : failed to read policy address info\n" ); return LIBIKE_FAILED; } char txtid_src[ LIBIKE_MAX_TEXTP2ID ]; char txtid_dst[ LIBIKE_MAX_TEXTP2ID ]; text_addr( txtid_src, &paddr_src, true, true ); text_addr( txtid_dst, &paddr_dst, true, true ); log.txt( LLOG_DECODE, "ii : - seq = 0x%08x\n" "ii : - spi = 0x%08x\n" "ii : - src = %s\n" "ii : - dst = %s\n", msg.header.sadb_msg_seq, ntohl( sa.spi ), txtid_src, txtid_dst ); // // convert the pfkey sainfo type // to a known isakmp protocol // unsigned char proto; switch( msg.header.sadb_msg_satype ) { case SADB_SATYPE_AH: proto = ISAKMP_PROTO_IPSEC_AH; break; case SADB_SATYPE_ESP: proto = ISAKMP_PROTO_IPSEC_ESP; break; case SADB_X_SATYPE_IPCOMP: proto = ISAKMP_PROTO_IPCOMP; break; default: { log.txt( LLOG_ERROR, "!! : unhandled pfkey spi protocol type %i\n", msg.header.sadb_msg_satype ); return LIBIKE_FAILED; } } // // locate the phase2 handler by // the message seqid // IDB_PH2 * ph2; if( !idb_list_ph2.find( true, &ph2, NULL, XCH_STATUS_ANY, XCH_STATUS_ANY, &msg.header.sadb_msg_seq, NULL, NULL, NULL ) ) { log.txt( LLOG_ERROR, "!! : unable to locate phase2 for getspi update ( msg seq = %u )\n", msg.header.sadb_msg_seq ); return LIBIKE_FAILED; } // // we only need to process update // message data associated with // inbound sas. // if( msg.header.sadb_msg_seq == ph2->seqid_out ) { ph2->dec( true ); return LIBIKE_OK; } // // step through the appropriate list // of proposals / transforms and set // the spi for all matched protocols // IKE_PROPOSAL * proposal; long pindex = 0; long pcount = 0; long tindex; long tcount; while( ph2->plist_l.nextp( &proposal, pindex, tindex, tcount ) ) { if( proposal->proto != proto ) continue; while( ph2->plist_l.nextt( &proposal, tindex ) ) { switch( proto ) { case ISAKMP_PROTO_IPSEC_AH: case ISAKMP_PROTO_IPSEC_ESP: proposal->spi.spi = sa.spi; proposal->spi.size = ISAKMP_SPI_SIZE; break; case ISAKMP_PROTO_IPCOMP: proposal->spi.cpi = ntohs( ( unsigned short ) ntohl( sa.spi ) ); proposal->spi.size = ISAKMP_CPI_SIZE; break; } } pcount++; } log.txt( LLOG_DEBUG, "ii : updated spi for %i %s proposal\n", pcount, find_name( NAME_PROTOCOL, proto ) ); // // once all spis have been accounted // for, we can initiate phase2 with // our peer // ph2->spicount--; if( ph2->spicount > 0 ) log.txt( LLOG_DEBUG, "ii : waiting for %i spi updates\n", ph2->spicount ); else { IDB_PH1 * ph1 = NULL; if( ph2->initiator ) { // // phase2 initiator // if( !idb_list_ph1.find( true, &ph1, ph2->tunnel, XCH_STATUS_MATURE, XCH_STATUS_EXPIRING, NULL ) ) { // // mark the phase2 as pending // ph2->status( XCH_STATUS_PENDING, XCH_NORMAL, 0 ); // // initiate a new phase1 // ph1 = new IDB_PH1( ph2->tunnel, true, NULL ); if( ph1 == NULL ) { ph2->dec( true ); return LIBIKE_FAILED; } if( !ph1->add( true ) ) { delete ph1; ph2->dec( true ); return LIBIKE_FAILED; } process_phase1_send( ph1 ); } } else { // // phase2 responder // if( !idb_list_ph1.find( true, &ph1, ph2->tunnel, XCH_STATUS_MATURE, XCH_STATUS_EXPIRING, &ph2->cookies ) ) { // // some gateways expect a response to // be protected using the same isakmp // sa it was initiated with. best to // ignore this and wait for another. // ph2->status( XCH_STATUS_DEAD, XCH_NORMAL, 0 ); ph2->dec( true ); return LIBIKE_FAILED; } } // // if we have a mature phase1 sa, // send the next phase2 message // if( ph1->status() >= XCH_STATUS_MATURE ) process_phase2_send( ph1, ph2 ); ph1->dec( true ); } // // cleanup // ph2->dec( true ); return LIBIKE_OK; } long _IKED::pfkey_recv_flush( PFKI_MSG & msg ) { idb_list_ph2.flush(); return LIBIKE_OK; } long _IKED::pfkey_recv_spdel( PFKI_MSG & msg ) { PFKI_SPINFO spinfo; memset( &spinfo, 0, sizeof( spinfo ) ); if( pfki.read_policy( msg, spinfo ) != IPCERR_OK ) { log.txt( LLOG_ERROR, "!! : failed to read spdel policy data\n" ); return LIBIKE_FAILED; } log.txt( LLOG_DECODE, "ii : - id = %i\n" "ii : - type = %s\n" "ii : - dir = %s\n", spinfo.sp.id, pfki.name( NAME_SPTYPE, spinfo.sp.type ), pfki.name( NAME_SPDIR, spinfo.sp.dir ) ); // // locate the sp by id // IDB_POLICY * policy; if( !idb_list_policy.find( true, &policy, spinfo.sp.dir, spinfo.sp.type, NULL, &spinfo.sp.id, NULL, NULL, NULL, NULL ) ) { log.txt( LLOG_ERROR, "!! : failed to locate policy by id %i\n", spinfo.sp.id ); return LIBIKE_FAILED; } // // attempt to remove sp // policy->dec( true, true ); return LIBIKE_OK; } long _IKED::pfkey_recv_spflush( PFKI_MSG & msg ) { idb_list_policy.flush(); return LIBIKE_OK; } long _IKED::pfkey_send_getspi( IDB_POLICY * policy, IDB_PH2 * ph2 ) { PFKI_SAINFO sainfo; memset( &sainfo, 0, sizeof( sainfo ) ); // // determine natt port usage // IKE_SADDR saddr_l = ph2->tunnel->saddr_l; IKE_SADDR saddr_r = ph2->tunnel->saddr_r; bool use_ports = false; if( ph2->tunnel->natt_version != IPSEC_NATT_NONE ) { if( ph2->tunnel->natt_version == IPSEC_NATT_CISCO ) { socket_lookup_port( saddr_l, true ); set_sockport( saddr_r.saddr, ph2->tunnel->peer->natt_port ); } use_ports = true; } // // convert source and destination // and store sequence ids // sainfo.paddr_src.proto = IPSEC_PROTO_ANY; sainfo.paddr_dst.proto = IPSEC_PROTO_ANY; switch( policy->sp.dir ) { case IPSEC_DIR_INBOUND: cpy_sockaddr( saddr_r.saddr, sainfo.paddr_src.saddr, use_ports ); cpy_sockaddr( saddr_l.saddr, sainfo.paddr_dst.saddr, use_ports ); sainfo.seq = ph2->seqid_in; break; case IPSEC_DIR_OUTBOUND: cpy_sockaddr( saddr_l.saddr, sainfo.paddr_src.saddr, use_ports ); cpy_sockaddr( saddr_r.saddr, sainfo.paddr_dst.saddr, use_ports ); sainfo.seq = ph2->seqid_out; break; } // // configure the spiinfo parameters // char txtid_src[ LIBIKE_MAX_TEXTP2ID ]; char txtid_dst[ LIBIKE_MAX_TEXTP2ID ]; text_addr( txtid_src, &sainfo.paddr_src, true, true ); text_addr( txtid_dst, &sainfo.paddr_dst, true, true ); // // send a getspi request for // each policy protocol // long xindex = 0; while( xindex < PFKI_MAX_XFORMS ) { if( !policy->xforms[ xindex ].proto ) break; sainfo.sa2.mode = policy->xforms[ xindex ].mode; sainfo.sa2.reqid = policy->xforms[ xindex ].reqid; unsigned char proto; switch( policy->xforms[ xindex ].proto ) { case PROTO_IP_AH: proto = ISAKMP_PROTO_IPSEC_AH; sainfo.satype = SADB_SATYPE_AH; break; case PROTO_IP_ESP: proto = ISAKMP_PROTO_IPSEC_ESP; sainfo.satype = SADB_SATYPE_ESP; break; case PROTO_IP_IPCOMP: proto = ISAKMP_PROTO_IPCOMP; sainfo.satype = SADB_X_SATYPE_IPCOMP; sainfo.range.min = 0x100; sainfo.range.max = 0xffff; break; } // // step through all proposals and // store the request id to be used // when sending the update message. // if( policy->sp.dir == IPSEC_DIR_INBOUND ) { IKE_PROPOSAL * proposal; long pindex = 0; while( ph2->plist_l.get( &proposal, pindex++ ) ) { // // match the protocol type // if( proposal->proto != proto ) continue; // // copy the request id // proposal->reqid = ( uint16_t ) sainfo.sa2.reqid; } // // inbound spis are dictated by // our kernel. we will need to // wait for an update response // ph2->spicount++; } if( policy->sp.dir == IPSEC_DIR_OUTBOUND ) { // // step through all proposals and // store the request id to be used // when sending the update message // IKE_PROPOSAL * proposal; long pindex = 0; while( ph2->plist_r.get( &proposal, pindex++ ) ) { // // if the protocol type matches // then store the request id and // obtain the spi value // if( proposal->proto != proto ) continue; // // copy the request id // proposal->reqid = ( uint16_t ) sainfo.sa2.reqid; // // copy the spi value // if( proto != ISAKMP_PROTO_IPCOMP ) { sainfo.range.min = ntohl( proposal->spi.spi ); sainfo.range.max = ntohl( proposal->spi.spi ); } else { sainfo.range.min = ntohs( proposal->spi.cpi ); sainfo.range.max = ntohs( proposal->spi.cpi ); } } } // // send our getspi request to pfkey // log.txt( LLOG_DEBUG, "K> : send pfkey %s %s message\n", pfki.name( NAME_MSGTYPE, SADB_GETSPI ), pfki.name( NAME_SATYPE, sainfo.satype ) ); log.txt( LLOG_DECODE, "ii : - seq = 0x%08x\n" "ii : - mode = %s\n" "ii : - reqid = 0x%08x\n" "ii : - min = 0x%08x\n" "ii : - max = 0x%08x\n" "ii : - src = %s\n" "ii : - dst = %s\n", sainfo.seq, pfki.name( NAME_SPMODE, sainfo.sa2.mode ), sainfo.sa2.reqid, ntohl( sainfo.range.min ), ntohl( sainfo.range.max ), txtid_src, txtid_dst ); pfki.send_getspi( sainfo ); xindex++; } return LIBIKE_OK; } long _IKED::pfkey_send_update( IDB_PH2 * ph2, IKE_PROPOSAL * proposal, BDATA & ekey, BDATA & akey, long dir ) { PFKI_SAINFO sainfo; memset( &sainfo, 0, sizeof( sainfo ) ); // // determine natt port usage // IKE_SADDR saddr_l = ph2->tunnel->saddr_l; IKE_SADDR saddr_r = ph2->tunnel->saddr_r; bool use_ports = false; if( ph2->tunnel->natt_version != IPSEC_NATT_NONE ) { if( ph2->tunnel->natt_version == IPSEC_NATT_CISCO ) { socket_lookup_port( saddr_l, true ); set_sockport( saddr_r.saddr, ph2->tunnel->peer->natt_port ); } use_ports = true; } // // convert mode // switch( proposal->encap ) { case ISAKMP_ENCAP_TRANSPORT: case ISAKMP_ENCAP_VXX_UDP_TRANSPORT: case ISAKMP_ENCAP_RFC_UDP_TRANSPORT: sainfo.sa2.mode = IPSEC_MODE_TRANSPORT; break; case ISAKMP_ENCAP_TUNNEL: case ISAKMP_ENCAP_VXX_UDP_TUNNEL: case ISAKMP_ENCAP_RFC_UDP_TUNNEL: sainfo.sa2.mode = IPSEC_MODE_TUNNEL; break; } // // copy the request id // sainfo.sa2.reqid = proposal->reqid; // // convert encryption and message // authentication algorithms. also // include natt information if esp // protocol is using udp encap // switch( proposal->proto ) { case ISAKMP_PROTO_IPSEC_ESP: { sainfo.satype = SADB_SATYPE_ESP; sainfo.sa.spi = proposal->spi.spi; sainfo.sa.replay = PFKI_WINDSIZE; switch( proposal->xform ) { case ISAKMP_ESP_DES_IV64: case ISAKMP_ESP_DES: sainfo.sa.encrypt = SADB_EALG_DESCBC; break; case ISAKMP_ESP_3DES: sainfo.sa.encrypt = SADB_EALG_3DESCBC; break; case ISAKMP_ESP_CAST: sainfo.sa.encrypt = SADB_X_EALG_CAST128CBC; break; case ISAKMP_ESP_BLOWFISH: sainfo.sa.encrypt = SADB_X_EALG_BLOWFISHCBC; break; case ISAKMP_ESP_3IDEA: sainfo.sa.encrypt = SADB_EALG_DESCBC; break; case ISAKMP_ESP_DES_IV32: sainfo.sa.encrypt = SADB_EALG_DESCBC; break; case ISAKMP_ESP_AES: sainfo.sa.encrypt = SADB_X_EALG_AESCBC; break; case ISAKMP_ESP_NULL: sainfo.sa.encrypt = SADB_EALG_NULL; break; default: { log.txt( LLOG_ERROR, "!! : unhandled ESP transform %s ( %i )\n", find_name( NAME_XFORM_ESP, proposal->xform ), proposal->xform ); return LIBIKE_FAILED; } } switch( proposal->hash_id ) { case ISAKMP_AUTH_HMAC_MD5: sainfo.sa.auth = SADB_AALG_MD5HMAC; break; case ISAKMP_AUTH_HMAC_SHA1: sainfo.sa.auth = SADB_AALG_SHA1HMAC; break; case ISAKMP_AUTH_HMAC_SHA2_256: sainfo.sa.auth = SADB_X_AALG_SHA2_256HMAC; break; case ISAKMP_AUTH_HMAC_SHA2_384: sainfo.sa.auth = SADB_X_AALG_SHA2_384HMAC; break; case ISAKMP_AUTH_HMAC_SHA2_512: sainfo.sa.auth = SADB_X_AALG_SHA2_512HMAC; break; default: { log.txt( LLOG_ERROR, "!! : unhandled ESP auth type %s ( %i )\n", find_name( NAME_MAUTH, proposal->hash_id ), proposal->hash_id ); return LIBIKE_FAILED; } } #ifdef OPT_NATT # ifndef __APPLE__ switch( proposal->encap ) { case ISAKMP_ENCAP_TUNNEL: if( ph2->tunnel->natt_version == IPSEC_NATT_CISCO ) sainfo.natt.type = UDP_ENCAP_ESPINUDP; break; case ISAKMP_ENCAP_VXX_UDP_TUNNEL: case ISAKMP_ENCAP_RFC_UDP_TUNNEL: case ISAKMP_ENCAP_VXX_UDP_TRANSPORT: case ISAKMP_ENCAP_RFC_UDP_TRANSPORT: if( ph2->tunnel->natt_version >= IPSEC_NATT_V02 ) sainfo.natt.type = UDP_ENCAP_ESPINUDP; else sainfo.natt.type = UDP_ENCAP_ESPINUDP_NON_IKE; break; } if( sainfo.natt.type ) { switch( dir ) { case IPSEC_DIR_INBOUND: get_sockport( saddr_r.saddr, sainfo.natt.port_src ); get_sockport( saddr_l.saddr, sainfo.natt.port_dst ); break; case IPSEC_DIR_OUTBOUND: get_sockport( saddr_l.saddr, sainfo.natt.port_src ); get_sockport( saddr_r.saddr, sainfo.natt.port_dst ); break; } } # else // __APPLE__ switch( proposal->encap ) { case ISAKMP_ENCAP_TUNNEL: if( ph2->tunnel->natt_version == IPSEC_NATT_CISCO ) sainfo.sa.flags |= SADB_X_EXT_NATT; break; case ISAKMP_ENCAP_VXX_UDP_TUNNEL: case ISAKMP_ENCAP_RFC_UDP_TUNNEL: case ISAKMP_ENCAP_VXX_UDP_TRANSPORT: case ISAKMP_ENCAP_RFC_UDP_TRANSPORT: sainfo.sa.flags |= SADB_X_EXT_NATT; break; } if( sainfo.sa.flags & SADB_X_EXT_NATT ) { sainfo.sa.flags |= SADB_X_EXT_NATT_KEEPALIVE; get_sockport( saddr_l.saddr, sainfo.sa.natt_port ); sainfo.sa.natt_port = ntohs( sainfo.sa.natt_port ); } # endif // __APPLE__ #endif // OPT_NATT break; } case ISAKMP_PROTO_IPSEC_AH: { sainfo.satype = SADB_SATYPE_AH; sainfo.sa.spi = proposal->spi.spi; switch( proposal->xform ) { case ISAKMP_AH_MD5: sainfo.sa.auth = SADB_AALG_MD5HMAC; break; case ISAKMP_AH_SHA: sainfo.sa.auth = SADB_AALG_SHA1HMAC; break; case ISAKMP_AH_SHA256: sainfo.sa.auth = SADB_X_AALG_SHA2_256HMAC; break; case ISAKMP_AH_SHA384: sainfo.sa.auth = SADB_X_AALG_SHA2_384HMAC; break; case ISAKMP_AH_SHA512: sainfo.sa.auth = SADB_X_AALG_SHA2_512HMAC; break; default: { log.txt( LLOG_ERROR, "!! : unhandled AH transform %s ( %i )\n", find_name( NAME_XFORM_AH, proposal->xform ), proposal->xform ); return LIBIKE_FAILED; } } break; } case ISAKMP_PROTO_IPCOMP: { sainfo.satype = SADB_X_SATYPE_IPCOMP; sainfo.sa.spi = htonl( ntohs( proposal->spi.cpi ) ); switch( proposal->xform ) { case ISAKMP_IPCOMP_OUI: sainfo.sa.encrypt = SADB_X_CALG_OUI; break; case ISAKMP_IPCOMP_DEFLATE: sainfo.sa.encrypt = SADB_X_CALG_DEFLATE; break; case ISAKMP_IPCOMP_LZS: sainfo.sa.encrypt = SADB_X_CALG_LZS; break; default: { log.txt( LLOG_ERROR, "!! : unhandled IPCOMP transform %s ( %i )\n", find_name( NAME_XFORM_AH, proposal->xform ), proposal->xform ); return LIBIKE_FAILED; } } break; } default: { log.txt( LLOG_ERROR, "!! : unhandled ike protocol type %i\n", proposal->proto ); return LIBIKE_FAILED; } } // // convert lifetime values // sainfo.ltime_hard.addtime = proposal->life_sec; sainfo.ltime_hard.bytes = proposal->life_kbs * 1024; sainfo.ltime_soft.addtime = proposal->life_sec; sainfo.ltime_soft.addtime *= PFKEY_SOFT_LIFETIME_RATE; sainfo.ltime_soft.addtime /= 100; sainfo.ltime_soft.bytes = proposal->life_kbs * 1024; sainfo.ltime_soft.bytes *= PFKEY_SOFT_LIFETIME_RATE; sainfo.ltime_soft.bytes /= 100; // // convert source and destination // and store sequence ids // sainfo.paddr_src.proto = IPSEC_PROTO_ANY; sainfo.paddr_dst.proto = IPSEC_PROTO_ANY; switch( dir ) { case IPSEC_DIR_INBOUND: cpy_sockaddr( saddr_r.saddr, sainfo.paddr_src.saddr, use_ports ); cpy_sockaddr( saddr_l.saddr, sainfo.paddr_dst.saddr, use_ports ); sainfo.seq = ph2->seqid_in; break; case IPSEC_DIR_OUTBOUND: cpy_sockaddr( saddr_l.saddr, sainfo.paddr_src.saddr, use_ports ); cpy_sockaddr( saddr_r.saddr, sainfo.paddr_dst.saddr, use_ports ); sainfo.seq = ph2->seqid_out; break; } // // convert encryption keys // if( ekey.size() ) { sainfo.ekey.length = ( u_int16_t ) ekey.size(); memcpy( sainfo.ekey.keydata, ekey.buff(), ekey.size() ); } if( akey.size() ) { sainfo.akey.length = ( u_int16_t ) akey.size(); memcpy( sainfo.akey.keydata, akey.buff(), akey.size() ); } // // send sa update to pfkey // char txtid_src[ LIBIKE_MAX_TEXTP2ID ]; char txtid_dst[ LIBIKE_MAX_TEXTP2ID ]; text_addr( txtid_src, &sainfo.paddr_src, true, true ); text_addr( txtid_dst, &sainfo.paddr_dst, true, true ); long nametype = NAME_SAENCR; if( sainfo.satype == SADB_X_SATYPE_IPCOMP ) nametype = NAME_SACOMP; log.txt( LLOG_DEBUG, "K> : send pfkey %s %s message\n", pfki.name( NAME_MSGTYPE, SADB_UPDATE ), pfki.name( NAME_SATYPE, sainfo.satype ) ); log.txt( LLOG_DECODE, "ii : - spi = 0x%08x\n" "ii : - src = %s\n" "ii : - dst = %s\n" "ii : - encr = %s\n" "ii : - ekey = %i bits\n" "ii : - auth = %s\n" "ii : - akey = %i bits\n" "ii : - hard = %i\n" #ifndef OPT_NATT "ii : - soft = %i\n", #else "ii : - soft = %i\n" # ifndef __APPLE__ "ii : - natt = %s\n" "ii : - nsrc = %i\n" "ii : - ndst = %i\n", # else "ii : - natt = %s\n" "ii : - port = %i\n", # endif // __APPLE__ #endif // OPT_NATT ntohl( sainfo.sa.spi ), txtid_src, txtid_dst, pfki.name( nametype, sainfo.sa.encrypt ), sainfo.ekey.length * 8, pfki.name( NAME_SAAUTH, sainfo.sa.auth ), sainfo.akey.length * 8, long( sainfo.ltime_hard.addtime ), #ifndef OPT_NATT long( sainfo.ltime_soft.addtime ) ); #else long( sainfo.ltime_soft.addtime ), # ifndef __APPLE__ pfki.name( NAME_NTTYPE, sainfo.natt.type ), ntohs( sainfo.natt.port_src ), ntohs( sainfo.natt.port_dst ) ); # else pfki.name( NAME_NTTYPE, UDP_ENCAP_ESPINUDP ), ntohs( sainfo.sa.natt_port ) ); # endif // __APPLE__ #endif // OPT_NATT pfki.send_update( sainfo ); return LIBIKE_OK; } long _IKED::pfkey_send_delete( IDB_PH2 * ph2 ) { // // send a delete request for // each local protocol sa // IKE_PROPOSAL * proposal; long pindex = 0; while( ph2->plist_r.get( &proposal, pindex++ ) ) { PFKI_SAINFO sainfo; memset( &sainfo, 0, sizeof( sainfo ) ); // // determine natt port usage // IKE_SADDR saddr_l = ph2->tunnel->saddr_l; IKE_SADDR saddr_r = ph2->tunnel->saddr_r; bool use_ports = false; if( ph2->tunnel->natt_version != IPSEC_NATT_NONE ) { if( ph2->tunnel->natt_version == IPSEC_NATT_CISCO ) { socket_lookup_port( saddr_l, true ); set_sockport( saddr_r.saddr, ph2->tunnel->peer->natt_port ); } use_ports = true; } // // determine the sa endpoint addresses // cpy_sockaddr( saddr_l.saddr, sainfo.paddr_src.saddr, use_ports ); cpy_sockaddr( saddr_r.saddr, sainfo.paddr_dst.saddr, use_ports ); char txtid_src[ LIBIKE_MAX_TEXTP2ID ]; char txtid_dst[ LIBIKE_MAX_TEXTP2ID ]; text_addr( txtid_src, &sainfo.paddr_src, true, true ); text_addr( txtid_dst, &sainfo.paddr_dst, true, true ); // // determine the sa type and spi // switch( proposal->proto ) { case ISAKMP_PROTO_IPSEC_AH: sainfo.satype = SADB_SATYPE_AH; sainfo.sa.spi = proposal->spi.spi; break; case ISAKMP_PROTO_IPSEC_ESP: sainfo.satype = SADB_SATYPE_ESP; sainfo.sa.spi = proposal->spi.spi; break; case ISAKMP_PROTO_IPCOMP: sainfo.satype = SADB_X_SATYPE_IPCOMP; sainfo.sa.spi = htonl( ntohs( proposal->spi.cpi ) ); break; } log.txt( LLOG_DEBUG, "K> : send pfkey %s %s message\n", pfki.name( NAME_MSGTYPE, SADB_DELETE ), pfki.name( NAME_SATYPE, sainfo.satype ) ); log.txt( LLOG_DECODE, "ii : - spi = 0x%08x\n" "ii : - src = %s\n" "ii : - dst = %s\n", htonl( sainfo.sa.spi ), txtid_src, txtid_dst ); pfki.send_del( sainfo ); } pindex = 0; while( ph2->plist_l.get( &proposal, pindex++ ) ) { PFKI_SAINFO sainfo; memset( &sainfo, 0, sizeof( sainfo ) ); // // determine natt port usage // IKE_SADDR saddr_l = ph2->tunnel->saddr_l; IKE_SADDR saddr_r = ph2->tunnel->saddr_r; bool use_ports = false; if( ph2->tunnel->natt_version != IPSEC_NATT_NONE ) { if( ph2->tunnel->natt_version == IPSEC_NATT_CISCO ) { socket_lookup_port( saddr_l, true ); set_sockport( saddr_r.saddr, ph2->tunnel->peer->natt_port ); } use_ports = true; } // // determine the sa endpoint addresses // cpy_sockaddr( saddr_r.saddr, sainfo.paddr_src.saddr, use_ports ); cpy_sockaddr( saddr_l.saddr, sainfo.paddr_dst.saddr, use_ports ); char txtid_src[ LIBIKE_MAX_TEXTP2ID ]; char txtid_dst[ LIBIKE_MAX_TEXTP2ID ]; text_addr( txtid_src, &sainfo.paddr_src, true, true ); text_addr( txtid_dst, &sainfo.paddr_dst, true, true ); // // determine the sa type and spi // switch( proposal->proto ) { case ISAKMP_PROTO_IPSEC_AH: sainfo.satype = SADB_SATYPE_AH; sainfo.sa.spi = proposal->spi.spi; break; case ISAKMP_PROTO_IPSEC_ESP: sainfo.satype = SADB_SATYPE_ESP; sainfo.sa.spi = proposal->spi.spi; break; case ISAKMP_PROTO_IPCOMP: sainfo.satype = SADB_X_SATYPE_IPCOMP; sainfo.sa.spi = htonl( ntohs( proposal->spi.cpi ) ); break; } log.txt( LLOG_DEBUG, "K> : send pfkey %s %s message\n", pfki.name( NAME_MSGTYPE, SADB_DELETE ), pfki.name( NAME_SATYPE, sainfo.satype ) ); log.txt( LLOG_DECODE, "ii : - spi = 0x%08x\n" "ii : - src = %s\n" "ii : - dst = %s\n", htonl( sainfo.sa.spi ), txtid_src, txtid_dst ); pfki.send_del( sainfo ); } return LIBIKE_OK; } long _IKED::pfkey_send_spadd( PFKI_SPINFO * spinfo ) { log.txt( LLOG_DEBUG, "K> : send pfkey %s %s message\n", pfki.name( NAME_MSGTYPE, SADB_X_SPDADD ), pfki.name( NAME_SATYPE, SADB_SATYPE_UNSPEC ) ); long result = pfki.send_spadd( *spinfo ); if( result != IPCERR_OK ) return LIBIKE_FAILED; return LIBIKE_OK; } long _IKED::pfkey_send_spdel( PFKI_SPINFO * spinfo ) { log.txt( LLOG_DEBUG, "K> : send pfkey %s %s message\n", pfki.name( NAME_MSGTYPE, SADB_X_SPDDELETE2 ), pfki.name( NAME_SATYPE, SADB_SATYPE_UNSPEC ) ); long result = pfki.send_spdel( *spinfo ); if( result != IPCERR_OK ) return LIBIKE_FAILED; return LIBIKE_OK; } ike-2.2.1+dfsg/source/iked/ike.keyfile.cpp000066400000000000000000000510611223036517100203250ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "iked.h" // // opsenssl version compatibility // #if OPENSSL_VERSION_NUMBER >= 0x00908000L # define D2I_X509_CONST const #else # define D2I_X509_CONST #endif #if OPENSSL_VERSION_NUMBER >= 0x00907000L # define D2I_RSA_CONST const #else # define D2I_RSA_CONST #endif void log_openssl_errors() { const char * file; int line; while( true ) { unsigned long code = ERR_get_error_line( &file, &line ); if( code == 0 ) break; char buf[ 1024 ]; ERR_error_string_n( code, buf, sizeof( buf ) ); iked.log.txt( LLOG_LOUD, "!! : libeay : %s:%i\n" "!! : %s\n", file, line, buf ); } } bool cert_2_bdata( BDATA & cert, X509 * x509 ) { int size = i2d_X509( x509, NULL ); cert.size( size ); unsigned char * cert_buff = cert.buff(); if( i2d_X509( x509, &cert_buff ) < size ) return false; return true; } bool bdata_2_cert( X509 ** x509, BDATA & cert ) { D2I_X509_CONST unsigned char * cert_buff = cert.buff(); *x509 = d2i_X509( NULL, &cert_buff, ( long ) cert.size() ); if( *x509 == NULL ) return false; return true; } bool prvkey_rsa_2_bdata( BDATA & prvkey, RSA * rsa ) { int size = i2d_RSAPrivateKey( rsa, NULL ); prvkey.size( size ); unsigned char * prvkey_buff = prvkey.buff(); if( i2d_RSAPrivateKey( rsa, &prvkey_buff ) < size ) return false; return true; } bool bdata_2_prvkey_rsa( RSA ** rsa, BDATA & prvkey ) { D2I_RSA_CONST unsigned char * prvkey_buff = prvkey.buff(); *rsa = d2i_RSAPrivateKey( NULL, &prvkey_buff, ( long ) prvkey.size() ); if( *rsa == NULL ) return false; return true; } bool pubkey_rsa_2_bdata( BDATA & pubkey, RSA * rsa ) { int size = i2d_RSAPublicKey( rsa, NULL ); pubkey.size( size ); unsigned char * pubkey_buff = pubkey.buff(); if( i2d_RSAPublicKey( rsa, &pubkey_buff ) < size ) return false; return true; } bool bdata_2_pubkey_rsa( RSA ** rsa, BDATA & pubkey ) { D2I_RSA_CONST unsigned char * pubkey_buff = pubkey.buff(); *rsa = d2i_RSAPublicKey( NULL, &pubkey_buff, ( long ) pubkey.size() ); if( *rsa == NULL ) return false; return true; } // openssl pem password callback int password_cb( char * buf, int size, int rwflag, void * userdata ) { BDATA * fpass = ( BDATA * ) userdata; if( !fpass->size() ) return 0; memset( buf, 0, size ); if( size > fpass->size() ) size = fpass->size(); memcpy( buf, fpass->buff(), size ); return size; } bool cert_load_pem( BDATA & cert, FILE * fp, bool ca, BDATA & pass ) { fseek( fp, 0, SEEK_SET ); X509 * x509 = PEM_read_X509( fp, NULL, password_cb, &pass ); if( x509 == NULL ) return false; bool converted = cert_2_bdata( cert, x509 ); X509_free( x509 ); return converted; } bool cert_load_p12( BDATA & cert, FILE * fp, bool ca, BDATA & pass ) { // PKCS12 required a null terminated password BDATA nullpass; nullpass.set( pass ); nullpass.add( "", 1 ); fseek( fp, 0, SEEK_SET ); PKCS12 * p12 = d2i_PKCS12_fp( fp, NULL ); if( p12 == NULL ) return false; X509 * x509 = NULL; if( ca ) { STACK_OF( X509 ) * stack = NULL; if( PKCS12_parse( p12, nullpass.text(), NULL, NULL, &stack ) ) { if( stack != NULL ) { if( sk_X509_value( stack, 0 ) != NULL ) x509 = sk_X509_value( stack, 0 ); sk_X509_free( stack ); } } } else PKCS12_parse( p12, nullpass.text(), NULL, &x509, NULL ); PKCS12_free( p12 ); if( x509 == NULL ) return false; bool converted = cert_2_bdata( cert, x509 ); X509_free( x509 ); return converted; } long _IKED::cert_load( BDATA & cert, char * fpath, bool ca, BDATA & pass ) { #ifdef WIN32 FILE * fp; if( fopen_s( &fp, fpath, "rb" ) ) return FILE_PATH; #else FILE * fp = fopen( fpath, "rb" ); if( !fp ) return FILE_PATH; #endif bool loaded = cert_load_pem( cert, fp, ca, pass ); if( !loaded ) loaded = cert_load_p12( cert, fp, ca, pass ); fclose( fp ); if( !loaded ) { log_openssl_errors(); return FILE_FAIL; } return FILE_OK; } bool cert_load_pem( BDATA & cert, BDATA & input, bool ca, BDATA & pass ) { BIO * bp = BIO_new( BIO_s_mem() ); if( bp == NULL ) return false; if( BIO_write( bp, input.buff(), ( int ) input.size() ) < 0 ) { BIO_free_all( bp ); return false; } X509 * x509 = PEM_read_bio_X509( bp, NULL, password_cb, &pass ); BIO_free_all( bp ); if( x509 == NULL ) return false; bool converted = cert_2_bdata( cert, x509 ); X509_free( x509 ); return converted; } bool cert_load_p12( BDATA & cert, BDATA & input, bool ca, BDATA & pass ) { // PKCS12 required a null terminated password BDATA nullpass; nullpass.set( pass ); nullpass.add( "", 1 ); BIO * bp = BIO_new( BIO_s_mem() ); if( bp == NULL ) return false; if( BIO_write( bp, input.buff(), ( int ) input.size() ) < 0 ) { BIO_free_all( bp ); return false; } PKCS12 * p12 = d2i_PKCS12_bio( bp, NULL ); BIO_free_all( bp ); if( p12 == NULL ) return false; X509 * x509 = NULL; EVP_PKEY * evp_pkey = NULL; if( ca ) { STACK_OF( X509 ) * stack = NULL; if( PKCS12_parse( p12, ( const char * ) nullpass.buff(), NULL, NULL, &stack ) ) { if( stack != NULL ) { if( sk_X509_value( stack, 0 ) != NULL ) x509 = sk_X509_value( stack, 0 ); sk_X509_free( stack ); } } } else PKCS12_parse( p12, ( const char * ) nullpass.buff(), &evp_pkey, &x509, NULL ); EVP_PKEY_free( evp_pkey ); PKCS12_free( p12 ); if( x509 == NULL ) return false; bool converted = cert_2_bdata( cert, x509 ); X509_free( x509 ); return converted; } long _IKED::cert_load( BDATA & cert, BDATA & input, bool ca, BDATA & pass ) { bool loaded = cert_load_pem( cert, input, ca, pass ); if( !loaded ) loaded = cert_load_p12( cert, input, ca, pass ); if( !loaded ) { log_openssl_errors(); return FILE_FAIL; } return FILE_OK; } bool _IKED::cert_desc( BDATA & cert, BDATA & desc ) { X509 * x509; if( !bdata_2_cert( &x509, cert ) ) return false; BIO * bio = BIO_new( BIO_s_mem() ); if( bio == NULL ) { X509_free( x509 ); return false; } if( X509_print( bio, x509 ) != 1 ) { BIO_free( bio ); X509_free( x509 ); return false; } unsigned char * bio_buff = NULL; int size = BIO_get_mem_data( bio, &bio_buff ); desc.size( size + 1 ); memcpy( desc.buff(), bio_buff, size ); BIO_free( bio ); X509_free( x509 ); return false; } bool _IKED::cert_subj( BDATA & cert, BDATA & subj ) { X509 * x509; if( !bdata_2_cert( &x509, cert ) ) return false; X509_NAME * x509_name = X509_get_subject_name( x509 ); if( x509_name == NULL ) { X509_free( x509 ); return false; } short size = i2d_X509_NAME( x509_name, NULL ); if( size > LIBIKE_MAX_VARID ) { X509_free( x509 ); return false; } subj.size( size ); unsigned char * temp = subj.buff(); size = i2d_X509_NAME( x509_name, &temp ); X509_free( x509 ); log.bin( LLOG_DEBUG, LLOG_DECODE, subj.buff(), subj.size(), "ii : obtained x509 cert subject" ); return true; } bool _IKED::asn1_text( BDATA & data, BDATA & text ) { X509_NAME * x509_name = NULL; D2I_X509_CONST unsigned char * buff = data.buff(); if( buff == NULL ) return false; d2i_X509_NAME( &x509_name, &buff, ( long ) data.size() ); if( x509_name == NULL ) return false; BIO * bio = BIO_new( BIO_s_mem() ); if( bio == NULL ) { X509_NAME_free( x509_name ); return false; } X509_NAME_print_ex( bio, x509_name, 0, XN_FLAG_SEP_COMMA_PLUS ); unsigned char * bio_buff = NULL; int bio_size = BIO_get_mem_data( bio, &bio_buff ); text.set( bio_buff, bio_size ); X509_NAME_free( x509_name ); BIO_free( bio ); return true; } bool _IKED::text_asn1( BDATA & text, BDATA & asn1 ) { BDATA temp; // // create a copy of our text // and reset the output buff // temp.set( text ); temp.add( 0, 1 ); asn1.del( true ); X509_NAME * name = X509_NAME_new(); unsigned char * fbuff = NULL; char * tbuff = ( char * ) temp.buff(); size_t tsize = 0; size_t tnext = 0; char * field = NULL; size_t fsize = 0; char * value = NULL; size_t vsize = 0; bool pair = false; bool stop = false; while( !stop ) { // // obtain the length of // the current segment // tsize = strcspn( tbuff, ",/=" ); // // check for null length // if( !tsize ) { tbuff++; continue; } // // check the delimiter type // switch( tbuff[ tsize ] ) { // // are we delimiting between a // field and value or between // a field value pair // case '=': { if( field == NULL ) field = tbuff; fsize += tsize; break; } case ',': case '/': case '\0': { if( field == NULL ) goto text_asn1_failed; if( value == NULL ) value = tbuff; vsize += tsize; if( !value[ vsize + 1 ] ) { pair = true; stop = true; break; } tnext = strcspn( tbuff + tsize + 1, ",/=" ); switch( value[ vsize + tnext + 1 ] ) { case ',': case '/': case '\0': vsize++; break; default: pair = true; break; } } } // // check for field value pair // if( pair ) { // // trim pair // while( ( field[ 0 ] == ' ' ) && fsize ) { field++; fsize--; } while( ( field[ fsize - 1 ] == ' ' ) && fsize ) fsize--; while( ( value[ 0 ] == ' ' ) && vsize ) { value++; vsize--; } while( ( value[ vsize - 1 ] == ' ' ) && vsize ) vsize--; // // null terminate // field[ fsize ] = 0; value[ vsize ] = 0; // // add the pair // X509_NAME_add_entry_by_txt( name, field, MBSTRING_ASC, ( unsigned char * ) value, -1, -1, 0 ); log.txt( LLOG_DECODE, "ii : asn1_text %s = %s\n", field, value ); // // cleanup for next pair // field = NULL; fsize = 0; value = NULL; vsize = 0; pair = false; } tbuff += ( tsize + 1 ); } // // copy to buffer // tsize = i2d_X509_NAME( name, NULL ); if( !tsize ) goto text_asn1_failed; asn1.size( tsize ); fbuff = asn1.buff(); tsize = i2d_X509_NAME( name, &fbuff ); if( !tsize ) goto text_asn1_failed; // // return success // X509_NAME_free( name ); return true; // // return failure // text_asn1_failed: X509_NAME_free( name ); return false; } // openssl certificate verify callback static int verify_cb( int ok, X509_STORE_CTX * store_ctx ) { if( !ok ) { long ll = LLOG_ERROR; char name[ 512 ]; X509_NAME * x509_name = X509_get_subject_name( store_ctx->current_cert ); X509_NAME_oneline( x509_name, name, 512 ); switch( store_ctx->error ) { case X509_V_ERR_UNABLE_TO_GET_CRL: ok = 1; ll = LLOG_INFO; break; } iked.log.txt( ll, "ii : %s(%d) at depth:%d\n" "ii : subject :%s\n", X509_verify_cert_error_string( store_ctx->error ), store_ctx->error, store_ctx->error_depth, name ); } ERR_clear_error(); return ok; } STACK_OF( X509 ) * build_cert_stack( IDB_LIST_CERT & certs, BDATA & leaf ) { STACK_OF( X509 ) * chain = sk_X509_new_null(); leaf.del(); uint8_t type1; BDATA cert1; long index1 = 0; while( certs.get( type1, cert1, index1++ ) ) { X509 * x509_cert1; if( !bdata_2_cert( &x509_cert1, cert1 ) ) continue; unsigned long hash1 = X509_subject_name_hash( x509_cert1 ); uint8_t type2; BDATA cert2; long index2 = 0; while( certs.get( type2, cert2, index2++ ) ) { X509 * x509_cert2; if( !bdata_2_cert( &x509_cert2, cert2 ) ) continue; unsigned long hash2 = X509_issuer_name_hash( x509_cert2 ); X509_free( x509_cert2 ); if( hash1 == hash2 ) break; } if( index2 < certs.count() ) sk_X509_push( chain, x509_cert1 ); else { leaf = cert1; X509_free( x509_cert1 ); } } return chain; } bool _IKED::cert_verify( IDB_LIST_CERT & certs, BDATA & ca, BDATA & cert ) { int result = 0; // // create certificate storage // X509_STORE * store = X509_STORE_new(); if( store == NULL ) return false; X509_STORE_set_verify_cb_func( store, verify_cb ); X509_LOOKUP * lookup = X509_STORE_add_lookup( store, X509_LOOKUP_file() ); if( lookup == NULL ) { X509_STORE_free( store ); return false; } // // load ca and add to store // X509 * x509_ca; if( !bdata_2_cert( &x509_ca, ca ) ) { X509_STORE_free( store ); return false; } X509_STORE_add_cert( store, x509_ca ); #ifdef WIN32 // // add all certificates from a path // char tmppath[ MAX_PATH ]; sprintf_s( tmppath, MAX_PATH, "%s\\certificates\\*.*", path_ins ); WIN32_FIND_DATA ffd; memset( &ffd, 0, sizeof( ffd ) ); ffd.dwFileAttributes = FILE_ATTRIBUTE_NORMAL; HANDLE hff = FindFirstFile( tmppath, &ffd ); while( hff != NULL ) { sprintf_s( tmppath, MAX_PATH, "%s\\certificates\\%s", path_ins, ffd.cFileName ); if( X509_LOOKUP_load_file( lookup, tmppath, X509_FILETYPE_PEM ) != NULL ) log.txt( LLOG_DEBUG, "ii : added %s to x509 store\n", ffd.cFileName ); if( !FindNextFile( hff, &ffd ) ) hff = NULL; } #endif // // create certificate chain // STACK_OF( X509 ) * chain = build_cert_stack( certs, cert ); X509 * x509_cert; if( bdata_2_cert( &x509_cert, cert ) ) { // // create our store context // X509_STORE_CTX * store_ctx = X509_STORE_CTX_new(); if( store_ctx != NULL ) { // // iniitialize our store context // X509_STORE_CTX_init( store_ctx, store, x509_cert, chain ); X509_STORE_CTX_set_flags( store_ctx, X509_V_FLAG_CRL_CHECK ); X509_STORE_CTX_set_flags( store_ctx, X509_V_FLAG_CRL_CHECK_ALL ); // // verify our certificate and cleanup // result = X509_verify_cert( store_ctx ); X509_STORE_CTX_free( store_ctx ); } X509_free( x509_cert ); } // // cleanup // sk_X509_pop_free( chain, X509_free ); X509_free( x509_ca ); X509_STORE_free( store ); return ( result > 0 ); } bool prvkey_rsa_load_pem( BDATA & prvkey, FILE * fp, BDATA & pass ) { fseek( fp, 0, SEEK_SET ); EVP_PKEY * evp_pkey = PEM_read_PrivateKey( fp, NULL, password_cb, &pass ); if( evp_pkey == NULL ) return false; bool converted = prvkey_rsa_2_bdata( prvkey, evp_pkey->pkey.rsa ); EVP_PKEY_free( evp_pkey ); return converted; } bool prvkey_rsa_load_p12( BDATA & prvkey, FILE * fp, BDATA & pass ) { // PKCS12 required a null terminated password BDATA nullpass; nullpass.set( pass ); nullpass.add( "", 1 ); fseek( fp, 0, SEEK_SET ); PKCS12 * p12 = d2i_PKCS12_fp( fp, NULL ); if( p12 == NULL ) return false; EVP_PKEY * evp_pkey; PKCS12_parse( p12, nullpass.text(), &evp_pkey, NULL, NULL ); PKCS12_free( p12 ); if( evp_pkey == NULL ) return false; bool converted = prvkey_rsa_2_bdata( prvkey, evp_pkey->pkey.rsa ); EVP_PKEY_free( evp_pkey ); return converted; } long _IKED::prvkey_rsa_load( BDATA & prvkey, char * fpath, BDATA & pass ) { #ifdef WIN32 FILE * fp; if( fopen_s( &fp, fpath, "rb" ) ) return FILE_PATH; #else FILE * fp = fopen( fpath, "rb" ); if( !fp ) return FILE_PATH; #endif bool loaded = prvkey_rsa_load_pem( prvkey, fp, pass ); if( !loaded ) loaded = prvkey_rsa_load_p12( prvkey, fp, pass ); fclose( fp ); if( !loaded ) { log_openssl_errors(); return FILE_FAIL; } return FILE_OK; } bool prvkey_rsa_load_pem( BDATA & prvkey, BDATA & input, BDATA & pass ) { BIO * bp = BIO_new( BIO_s_mem() ); if( bp == NULL ) return false; if( BIO_write( bp, input.buff(), ( int ) input.size() ) < 0 ) { BIO_free_all( bp ); return false; } EVP_PKEY * evp_pkey = PEM_read_bio_PrivateKey( bp, NULL, password_cb, &pass ); BIO_free_all( bp ); if( evp_pkey == NULL ) return false; bool converted = prvkey_rsa_2_bdata( prvkey, evp_pkey->pkey.rsa ); EVP_PKEY_free( evp_pkey ); return converted; } bool prvkey_rsa_load_p12( BDATA & prvkey, BDATA & input, BDATA & pass ) { // PKCS12 required a null terminated password BDATA nullpass; nullpass.set( pass ); nullpass.add( "", 1 ); BIO * bp = BIO_new( BIO_s_mem() ); if( bp == NULL ) return false; if( BIO_write( bp, input.buff(), ( int ) input.size() ) < 0 ) { BIO_free_all( bp ); return false; } PKCS12 * p12 = d2i_PKCS12_bio( bp, NULL ); BIO_free_all( bp ); if( p12 == NULL ) return false; EVP_PKEY * evp_pkey; PKCS12_parse( p12, nullpass.text(), &evp_pkey, NULL, NULL ); PKCS12_free( p12 ); if( evp_pkey == NULL ) return false; bool converted = prvkey_rsa_2_bdata( prvkey, evp_pkey->pkey.rsa ); EVP_PKEY_free( evp_pkey ); return converted; } long _IKED::prvkey_rsa_load( BDATA & prvkey, BDATA & input, BDATA & pass ) { bool loaded = prvkey_rsa_load_pem( prvkey, input, pass ); if( !loaded ) loaded = prvkey_rsa_load_p12( prvkey, input, pass ); if( !loaded ) { log_openssl_errors(); return FILE_FAIL; } return FILE_OK; } bool _IKED::pubkey_rsa_read( BDATA & cert, BDATA & pubkey ) { X509 * x509; if( !bdata_2_cert( &x509, cert ) ) return false; EVP_PKEY * evp_pkey = X509_get_pubkey( x509 ); X509_free( x509 ); if( evp_pkey == NULL ) return false; bool result = pubkey_rsa_2_bdata( pubkey, evp_pkey->pkey.rsa ); EVP_PKEY_free( evp_pkey ); return result; } bool _IKED::prvkey_rsa_encrypt( BDATA & prvkey, BDATA & hash, BDATA & sign ) { RSA * rsa; if( !bdata_2_prvkey_rsa( &rsa, prvkey ) ) return false; int size = RSA_size( rsa ); sign.size( size ); size = RSA_private_encrypt( ( int ) hash.size(), hash.buff(), sign.buff(), rsa, RSA_PKCS1_PADDING ); if( size == -1 ) return false; RSA_free( rsa ); sign.size( size ); return true; } bool _IKED::pubkey_rsa_decrypt( BDATA & pubkey, BDATA & sign, BDATA & hash ) { RSA * rsa; if( !bdata_2_pubkey_rsa( &rsa, pubkey ) ) return false; int size = RSA_size( rsa ); hash.size( size ); size = RSA_public_decrypt( ( int ) sign.size(), sign.buff(), hash.buff(), rsa, RSA_PKCS1_PADDING ); if( size == -1 ) return false; RSA_free( rsa ); hash.size( size ); return true; } ike-2.2.1+dfsg/source/iked/ike.names.cpp000066400000000000000000000541051223036517100200020ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "iked.h" const char * _IKED::find_name( long type, long id ) { static const char * unknown1 = "unknown type"; static const char * unknown2 = "unknown"; switch( type ) { case NAME_INITIATOR: { static const char * init0 = "responder"; static const char * init1 = "initiator"; switch( id ) { case 0: return init0; case 1: return init1; default: return unknown2; } } case NAME_EXCHANGE: { static const char * exchange1 = "base"; static const char * exchange2 = "identity protect"; static const char * exchange3 = "authenticateon only"; static const char * exchange4 = "aggressive"; static const char * exchange5 = "informational"; static const char * exchange6 = "isakmp config / xauth"; switch( id ) { case ISAKMP_EXCH_BASE: return exchange1; case ISAKMP_EXCH_IDENT_PROTECT: return exchange2; case ISAKMP_EXCH_AUTHENTICATION: return exchange3; case ISAKMP_EXCH_AGGRESSIVE: return exchange4; case ISAKMP_EXCH_INFORMATIONAL: return exchange5; case ISAKMP_EXCH_CONFIG: return exchange6; default: return unknown2; } } case NAME_PROTOCOL: { static const char * proto1 = "isakmp"; static const char * proto2 = "ipsec-ah"; static const char * proto3 = "ipsec-esp"; static const char * proto4 = "ipcomp"; switch( id ) { case ISAKMP_PROTO_ISAKMP: return proto1; case ISAKMP_PROTO_IPSEC_AH: return proto2; case ISAKMP_PROTO_IPSEC_ESP: return proto3; case ISAKMP_PROTO_IPCOMP: return proto4; default: return unknown2; } } case NAME_XFORM_ISAKMP: { static const char * xform1 = "ike"; switch( id ) { case ISAKMP_KEY_IKE: return xform1; default: return unknown2; } } case NAME_XFORM_AH: { static const char * xform1 = "ah-md5"; static const char * xform2 = "ah-sha"; static const char * xform3 = "ah-des"; static const char * xform4 = "ah-sha256"; static const char * xform5 = "ah-sha384"; static const char * xform6 = "ah-sha512"; switch( id ) { case ISAKMP_AH_MD5: return xform1; case ISAKMP_AH_SHA: return xform2; case ISAKMP_AH_DES: return xform3; case ISAKMP_AH_SHA256: return xform4; case ISAKMP_AH_SHA384: return xform5; case ISAKMP_AH_SHA512: return xform6; default: return unknown2; } } case NAME_XFORM_ESP: { static const char * xform1 = "esp-des-iv64"; static const char * xform2 = "esp-des"; static const char * xform3 = "esp-3des"; static const char * xform4 = "esp-rc5"; static const char * xform5 = "esp-idea"; static const char * xform6 = "esp-cast"; static const char * xform7 = "esp-blowfish"; static const char * xform8 = "esp-3idea"; static const char * xform9 = "esp-des-iv32"; static const char * xform10 = "esp-rc4"; static const char * xform11 = "esp-null"; static const char * xform12 = "esp-aes"; switch( id ) { case ISAKMP_ESP_DES_IV64: return xform1; case ISAKMP_ESP_DES: return xform2; case ISAKMP_ESP_3DES: return xform3; case ISAKMP_ESP_RC5: return xform4; case ISAKMP_ESP_IDEA: return xform5; case ISAKMP_ESP_CAST: return xform6; case ISAKMP_ESP_BLOWFISH: return xform7; case ISAKMP_ESP_3IDEA: return xform8; case ISAKMP_ESP_DES_IV32: return xform9; case ISAKMP_ESP_RC4: return xform10; case ISAKMP_ESP_NULL: return xform11; case ISAKMP_ESP_AES: return xform12; default: return unknown2; } } case NAME_XFORM_IPCOMP: { static const char * xform0 = "none"; static const char * xform1 = "ipcomp-oui"; static const char * xform2 = "ipcomp-deflate"; static const char * xform3 = "ipcomp-lzs"; switch( id ) { case ISAKMP_IPCOMP_NONE: return xform0; case ISAKMP_IPCOMP_OUI: return xform1; case ISAKMP_IPCOMP_DEFLATE: return xform2; case ISAKMP_IPCOMP_LZS: return xform3; default: return unknown2; } } case NAME_PAYLOAD: { static const char * pload0 = "none"; static const char * pload1 = "security association"; static const char * pload2 = "proposal"; static const char * pload3 = "transform"; static const char * pload4 = "key exchange"; static const char * pload5 = "identity"; static const char * pload6 = "certificate"; static const char * pload7 = "certificate request"; static const char * pload8 = "hash"; static const char * pload9 = "signature"; static const char * pload10 = "nonce"; static const char * pload11 = "notify"; static const char * pload12 = "delete"; static const char * pload13 = "vendor"; static const char * pload14 = "attribute"; static const char * pload15 = "nat discovery draft"; static const char * pload16 = "nat original adress draft"; static const char * pload17 = "nat discovery rfc"; static const char * pload18 = "nat original adress rfc"; static const char * pload19 = "fragment"; switch( id ) { case ISAKMP_PAYLOAD_NONE: return pload0; case ISAKMP_PAYLOAD_SA: return pload1; case ISAKMP_PAYLOAD_PROPOSAL: return pload2; case ISAKMP_PAYLOAD_TRANSFORM: return pload3; case ISAKMP_PAYLOAD_KEX: return pload4; case ISAKMP_PAYLOAD_IDENT: return pload5; case ISAKMP_PAYLOAD_CERT: return pload6; case ISAKMP_PAYLOAD_CERT_REQ: return pload7; case ISAKMP_PAYLOAD_HASH: return pload8; case ISAKMP_PAYLOAD_SIGNATURE: return pload9; case ISAKMP_PAYLOAD_NONCE: return pload10; case ISAKMP_PAYLOAD_NOTIFY: return pload11; case ISAKMP_PAYLOAD_DELETE: return pload12; case ISAKMP_PAYLOAD_VEND: return pload13; case ISAKMP_PAYLOAD_ATTRIB: return pload14; case ISAKMP_PAYLOAD_NAT_VXX_DISC: return pload15; case ISAKMP_PAYLOAD_NAT_VXX_ORIG: return pload16; case ISAKMP_PAYLOAD_NAT_RFC_DISC: return pload17; case ISAKMP_PAYLOAD_NAT_RFC_ORIG: return pload18; case ISAKMP_PAYLOAD_FRAGMENT: return pload19; default: return unknown2; } } case NAME_CIPHER: { static const char * cipher1 = "des"; static const char * cipher2 = "idea"; static const char * cipher3 = "blowfish"; static const char * cipher4 = "rc5"; static const char * cipher5 = "3des"; static const char * cipher6 = "cast"; static const char * cipher7 = "aes"; switch( id ) { case IKE_CIPHER_DES: return cipher1; case IKE_CIPHER_IDEA: return cipher2; case IKE_CIPHER_BLOWFISH: return cipher3; case IKE_CIPHER_RC5_R16_B64: return cipher4; case IKE_CIPHER_3DES: return cipher5; case IKE_CIPHER_CAST: return cipher6; case IKE_CIPHER_AES: return cipher7; default: return unknown2; } } case NAME_PAUTH: { static const char * auth1 = "psk"; static const char * auth2 = "sig-dsa"; static const char * auth3 = "sig-rsa"; static const char * auth4 = "rsa-encrypt"; static const char * auth5 = "rsa-revised"; static const char * auth6 = "hybrid-initiator-rsa"; static const char * auth7 = "hybrid-responder-rsa"; static const char * auth8 = "hybrid-initiator-dss"; static const char * auth9 = "hybrid-responder-dss"; static const char * auth10 = "xauth-initiator-psk"; static const char * auth11 = "xauth-responder-psk"; static const char * auth12 = "xauth-initiator-dss"; static const char * auth13 = "xauth-responder-dss"; static const char * auth14 = "xauth-initiator-rsa"; static const char * auth15 = "xauth-responder-rsa"; static const char * auth16 = "xauth-initiator-rsa-encryption"; static const char * auth17 = "xauth-responder-rsa-encryption"; static const char * auth18 = "xauth-initiator-rsa-revised-encryption"; static const char * auth19 = "xauth-responder-rsa-revised-encryption"; switch( id ) { case IKE_AUTH_PRESHARED_KEY: return auth1; case IKE_AUTH_SIG_DSA: return auth2; case IKE_AUTH_SIG_RSA: return auth3; case IKE_AUTH_SIG_RSA_ENCRYPT: return auth4; case IKE_AUTH_SIG_RSA_REVISED: return auth5; case HYBRID_AUTH_INIT_RSA: return auth6; case HYBRID_AUTH_RESP_RSA: return auth7; case HYBRID_AUTH_INIT_DSS: return auth8; case HYBRID_AUTH_RESP_DSS: return auth9; case XAUTH_AUTH_INIT_PSK: return auth10; case XAUTH_AUTH_RESP_PSK: return auth11; case XAUTH_AUTH_INIT_DSS: return auth12; case XAUTH_AUTH_RESP_DSS: return auth13; case XAUTH_AUTH_INIT_RSA: return auth14; case XAUTH_AUTH_RESP_RSA: return auth15; case XAUTH_AUTH_INIT_RSA_ENC: return auth16; case XAUTH_AUTH_RESP_RSA_ENC: return auth17; case XAUTH_AUTH_INIT_RSA_REV: return auth18; case XAUTH_AUTH_RESP_RSA_REV: return auth19; default: return unknown2; } } case NAME_MAUTH: { static const char * hash1 = "hmac-md5"; static const char * hash2 = "hmac-sha1"; static const char * hash3 = "des-mac"; static const char * hash4 = "kpdk"; static const char * hash5 = "hmac-sha2-256"; static const char * hash6 = "hmac-sha2-384"; static const char * hash7 = "hmac-sha2-512"; switch( id ) { case ISAKMP_AUTH_HMAC_MD5: return hash1; case ISAKMP_AUTH_HMAC_SHA1: return hash2; case ISAKMP_AUTH_DES_MAC: return hash3; case ISAKMP_AUTH_KPDK: return hash4; case ISAKMP_AUTH_HMAC_SHA2_256: return hash5; case ISAKMP_AUTH_HMAC_SHA2_384: return hash6; case ISAKMP_AUTH_HMAC_SHA2_512: return hash7; default: return unknown2; } } case NAME_HASH: { static const char * hash1 = "md5"; static const char * hash2 = "sha1"; static const char * hash3 = "tiger"; static const char * hash4 = "sha2-256"; static const char * hash5 = "sha2-384"; static const char * hash6 = "sha2-512"; switch( id ) { case IKE_HASH_MD5: return hash1; case IKE_HASH_SHA1: return hash2; case IKE_HASH_TIGER: return hash3; case IKE_HASH_SHA2_256: return hash4; case IKE_HASH_SHA2_384: return hash5; case IKE_HASH_SHA2_512: return hash6; default: return unknown2; } } case NAME_CERT: { static const char * cert0 = "none"; static const char * cert1 = "pkcs7"; static const char * cert2 = "pgp"; static const char * cert3 = "dns signed"; static const char * cert4 = "x.509 signed"; static const char * cert5 = "x.509 key exchange"; static const char * cert6 = "kerberos"; static const char * cert7 = "certificate revocation list ( CRL )"; static const char * cert8 = "authority revocation list ( ARL )"; static const char * cert9 = "spki"; static const char * cert10 = "x.509 attribute"; static const char * cert11 = "plain rsa"; switch( id ) { case ISAKMP_CERT_NONE: return cert0; case ISAKMP_CERT_PKCS7: return cert1; case ISAKMP_CERT_PGP: return cert2; case ISAKMP_CERT_DNS_SIGNED: return cert3; case ISAKMP_CERT_X509_SIG: return cert4; case ISAKMP_CERT_X509_KEX: return cert5; case ISAKMP_CERT_KERBEROS: return cert6; case ISAKMP_CERT_CRL: return cert7; case ISAKMP_CERT_ARL: return cert8; case ISAKMP_CERT_SPKI: return cert9; case ISAKMP_CERT_X509_ATTR: return cert10; case ISAKMP_CERT_RSA_PLAIN: return cert11; default: return unknown2; } } case NAME_GROUP: { static const char * group0 = "none"; static const char * group1 = "group1 ( modp-768 )"; static const char * group2 = "group2 ( modp-1024 )"; static const char * group3 = "group3 ( ecn-155 )"; static const char * group4 = "group4 ( ecn-185 )"; static const char * group5 = "group5 ( modp-1536 )"; static const char * group14 = "group14 ( modp-2048 )"; static const char * group15 = "group15 ( modp-3072 )"; static const char * group16 = "group16 ( modp-4096 )"; static const char * group17 = "group17 ( modp-6144 )"; static const char * group18 = "group18 ( modp-8192 )"; switch( id ) { case 0: return group0; case IKE_GRP_GROUP1: return group1; case IKE_GRP_GROUP2: return group2; case IKE_GRP_GROUP3: return group3; case IKE_GRP_GROUP4: return group4; case IKE_GRP_GROUP5: return group5; case IKE_GRP_GROUP14: return group14; case IKE_GRP_GROUP15: return group15; case IKE_GRP_GROUP16: return group16; case IKE_GRP_GROUP17: return group17; case IKE_GRP_GROUP18: return group18; default: return unknown2; } } case NAME_ENCAP: { static const char * encap1 = "tunnel"; static const char * encap2 = "transport"; static const char * encap3 = "udp-tunnel ( draft )"; static const char * encap4 = "udp-transport ( draft )"; static const char * encap5 = "udp-tunnel ( rfc )"; static const char * encap6 = "udp-transport ( rfc )"; switch( id ) { case ISAKMP_ENCAP_TUNNEL: return encap1; case ISAKMP_ENCAP_TRANSPORT: return encap2; case ISAKMP_ENCAP_VXX_UDP_TUNNEL: return encap3; case ISAKMP_ENCAP_VXX_UDP_TRANSPORT: return encap4; case ISAKMP_ENCAP_RFC_UDP_TUNNEL: return encap5; case ISAKMP_ENCAP_RFC_UDP_TRANSPORT: return encap6; default: return unknown2; } } case NAME_IDENT: { static const char * ident0 = "none"; static const char * ident1 = "ipv4-host"; static const char * ident2 = "fqdn"; static const char * ident3 = "user-fqdn"; static const char * ident4 = "ipv4-subnet"; static const char * ident5 = "ipv6-host"; static const char * ident6 = "ipv6-subnet"; static const char * ident7 = "ipv4-range"; static const char * ident8 = "ipv4-range"; static const char * ident9 = "asn1-dn"; static const char * ident10 = "asn1-gn"; static const char * ident11 = "key-id"; switch( id ) { case ISAKMP_ID_NONE: return ident0; case ISAKMP_ID_IPV4_ADDR: return ident1; case ISAKMP_ID_FQDN: return ident2; case ISAKMP_ID_USER_FQDN: return ident3; case ISAKMP_ID_IPV4_ADDR_SUBNET: return ident4; case ISAKMP_ID_IPV6_ADDR: return ident5; case ISAKMP_ID_IPV6_ADDR_SUBNET: return ident6; case ISAKMP_ID_IPV4_ADDR_RANGE: return ident7; case ISAKMP_ID_IPV6_ADDR_RANGE: return ident8; case ISAKMP_ID_ASN1_DN: return ident9; case ISAKMP_ID_ASN1_GN: return ident10; case ISAKMP_ID_KEY_ID: return ident11; default: return unknown2; } } case NAME_NOTIFY: { static const char * notify1 = "INVALID-PAYLOAD-TYPE"; static const char * notify2 = "DOI-NOT-SUPPORTED"; static const char * notify3 = "SITUATION-NOT-SUPPORTED"; static const char * notify4 = "INVALID-COOKIE"; static const char * notify5 = "INVALID-MAJOR-VERSION"; static const char * notify6 = "INVALID-MINOR-VERSION"; static const char * notify7 = "INVALID-EXCHANGE-TYPE"; static const char * notify8 = "INVALID-FLAGS"; static const char * notify9 = "INVALID-MESSAGE-ID"; static const char * notify10 = "INVALID-PROTOCOL-ID"; static const char * notify11 = "INVALID-SPI"; static const char * notify12 = "INVALID-TRANSFORM-ID"; static const char * notify13 = "ATTRIBUTES-NOT-SUPPORTED"; static const char * notify14 = "NO-PROPOSAL-CHOSEN"; static const char * notify15 = "BAD-PROPOSAL-SYNTAX"; static const char * notify16 = "PAYLOAD-MALFORMED"; static const char * notify17 = "INVALID-KEY-INFORMATION"; static const char * notify18 = "INVALID-ID-INFORMATION"; static const char * notify19 = "INVALID-CERT-ENCODING"; static const char * notify20 = "INVALID-CERTIFICATE"; static const char * notify21 = "CERT-TYPE-UNSUPPORTED"; static const char * notify22 = "INVALID-CERT-AUTHORITY"; static const char * notify23 = "INVALID-HASH-INFORMATION"; static const char * notify24 = "AUTHENTICATION-FAILED"; static const char * notify25 = "INVALID-SIGNATURE"; static const char * notify26 = "ADDRESS-NOTIFICATION"; static const char * notify27 = "NOTIFY-SA-LIFETIME"; static const char * notify28 = "CERTIFICATE-UNAVAILABLE"; static const char * notify29 = "UNSUPPORTED-EXCHANGE-TYPE"; static const char * notify30 = "UNEQUAL-PAYLOAD-LENGTHS"; static const char * notify31 = "RESPONDER-LIFETIME"; static const char * notify32 = "REPLAY-STATUS"; static const char * notify33 = "INITIAL-CONTACT"; static const char * notify34 = "UNITY-LOAD-BALANCE"; static const char * notify35 = "UNITY-GROUP-HASH"; static const char * notify36 = "DPDV1-R-U-THERE"; static const char * notify37 = "DPDV1-R-U-THERE-ACK"; switch( id ) { case ISAKMP_N_INVALID_PAYLOAD_TYPE: return notify1; case ISAKMP_N_DOI_NOT_SUPPORTED: return notify2; case ISAKMP_N_SITUATION_NOT_SUPPORTED: return notify3; case ISAKMP_N_INVALID_COOKIE: return notify4; case ISAKMP_N_INVALID_MAJOR_VERSION: return notify5; case ISAKMP_N_INVALID_MINOR_VERSION: return notify6; case ISAKMP_N_INVALID_EXCHANGE_TYPE: return notify7; case ISAKMP_N_INVALID_FLAGS: return notify8; case ISAKMP_N_INVALID_MESSAGE_ID: return notify9; case ISAKMP_N_INVALID_PROTOCOL_ID: return notify10; case ISAKMP_N_INVALID_SPI: return notify11; case ISAKMP_N_INVALID_TRANSFORM_ID: return notify12; case ISAKMP_N_ATTRIBUTES_NOT_SUPPORTED: return notify13; case ISAKMP_N_NO_PROPOSAL_CHOSEN: return notify14; case ISAKMP_N_BAD_PROPOSAL_SYNTAX: return notify15; case ISAKMP_N_PAYLOAD_MALFORMED: return notify16; case ISAKMP_N_INVALID_KEY_INFORMATION: return notify17; case ISAKMP_N_INVALID_ID_INFORMATION: return notify18; case ISAKMP_N_INVALID_CERT_ENCODING: return notify19; case ISAKMP_N_INVALID_CERTIFICATE: return notify20; case ISAKMP_N_CERT_TYPE_UNSUPPORTED: return notify21; case ISAKMP_N_INVALID_CERT_AUTHORITY: return notify22; case ISAKMP_N_INVALID_HASH_INFORMATION: return notify23; case ISAKMP_N_AUTHENTICATION_FAILED: return notify24; case ISAKMP_N_INVALID_SIGNATURE: return notify25; case ISAKMP_N_ADDRESS_NOTIFICATION: return notify26; case ISAKMP_N_NOTIFY_SA_LIFETIME: return notify27; case ISAKMP_N_CERTIFICATE_UNAVAILABLE: return notify28; case ISAKMP_N_UNSUPPORTED_EXCHANGE_TYPE: return notify29; case ISAKMP_N_UNEQUAL_PAYLOAD_LENGTHS: return notify30; case ISAKMP_N_RESPONDER_LIFETIME: return notify31; case ISAKMP_N_REPLAY_STATUS: return notify32; case ISAKMP_N_INITIAL_CONTACT: return notify33; case ISAKMP_N_UNITY_LOAD_BALANCE: return notify34; case ISAKMP_N_UNITY_GROUP_HASH: return notify35; case ISAKMP_N_DPD_R_U_THERE: return notify36; case ISAKMP_N_DPD_R_U_THERE_ACK: return notify37; default: return unknown2; } } default: return unknown1; } } ike-2.2.1+dfsg/source/iked/ike.nethlp.cpp000066400000000000000000000230261223036517100201670ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "iked.h" // // general network helper functions // void _IKED::text_prot( char * text, int prot ) { static const char * prot_00 = "ANY"; static const char * prot_01 = "ICMP"; static const char * prot_04 = "IPIP"; static const char * prot_06 = "TCP"; static const char * prot_17 = "UDP"; static const char * prot_47 = "GRE"; static const char * prot_50 = "ESP"; static const char * prot_51 = "AH"; const char * temp = NULL; switch( prot ) { case 0: temp = prot_00; break; case 1: temp = prot_01; break; case 4: temp = prot_04; break; case 6: temp = prot_06; break; case 17: temp = prot_17; break; case 47: temp = prot_47; break; case 50: temp = prot_50; break; case 51: temp = prot_51; break; } if( temp != NULL ) strcpy_s( text, LIBIKE_MAX_TEXTPROT, temp ); else sprintf_s( text, LIBIKE_MAX_TEXTPROT, "%i", prot ); } void _IKED::text_addr( char * text, in_addr & addr ) { unsigned long haddr = ntohl( addr.s_addr ); sprintf_s( text, LIBIKE_MAX_TEXTADDR, "%lu.%lu.%lu.%lu", 0xff & ( haddr >> 24 ), 0xff & ( haddr >> 16 ), 0xff & ( haddr >> 8 ), 0xff & haddr ); } void _IKED::text_mask( char * text, in_addr & addr ) { unsigned long bits; unsigned long mask; bits = 0; mask = ntohl( addr.s_addr ); while( mask & 0x80000000 ) { mask <<= 1; bits++; } sprintf_s( text, LIBIKE_MAX_TEXTADDR, "%lu", bits ); } void _IKED::text_port( char * text, int port ) { if( !port ) strcpy_s( text, LIBIKE_MAX_TEXTPORT, "*" ); else sprintf_s( text, LIBIKE_MAX_TEXTPORT, "%i", ntohs( port ) ); } void _IKED::text_addr( char * text, sockaddr * saddr, bool port ) { switch( saddr->sa_family ) { case AF_INET: { sockaddr_in * saddr_in = ( sockaddr_in * ) saddr; char txtaddr[ LIBIKE_MAX_TEXTADDR ]; text_addr( txtaddr, saddr_in->sin_addr ); if( port ) { sprintf_s( text, LIBIKE_MAX_TEXTADDR, "%s:%u", txtaddr, ntohs( saddr_in->sin_port ) ); } else { sprintf_s( text, LIBIKE_MAX_TEXTADDR, "%s", txtaddr ); } break; } default: sprintf_s( text, LIBIKE_MAX_TEXTADDR, "" ); } } void _IKED::text_addr( char * text, IKE_SADDR * iaddr, bool port ) { text_addr( text, &iaddr->saddr, port ); } void _IKED::text_addr( char * text, PFKI_ADDR * paddr, bool port, bool netmask ) { char txtaddr[ LIBIKE_MAX_TEXTADDR ]; text_addr( txtaddr, &paddr->saddr, port ); if( netmask && paddr->prefix ) { sprintf_s( text, LIBIKE_MAX_TEXTADDR, "%s/%u", txtaddr, paddr->prefix ); } else { sprintf_s( text, LIBIKE_MAX_TEXTADDR, "%s", txtaddr ); } } void _IKED::text_ph1id( char * text, IKE_PH1ID * ph1id ) { switch( ph1id->type ) { case ISAKMP_ID_NONE: { sprintf_s( text, LIBIKE_MAX_TEXTP1ID, "%s", find_name( NAME_IDENT, ph1id->type ) ); break; } case ISAKMP_ID_IPV4_ADDR: { char txtaddr[ LIBIKE_MAX_TEXTADDR ]; text_addr( txtaddr, ph1id->addr ); sprintf_s( text, LIBIKE_MAX_TEXTP1ID, "%s %s", find_name( NAME_IDENT, ph1id->type ), txtaddr ); break; } case ISAKMP_ID_FQDN: case ISAKMP_ID_USER_FQDN: { BDATA varid; varid.set( ph1id->varid ); varid.add( 0, 1 ); sprintf_s( text, LIBIKE_MAX_TEXTP1ID, "%s %s", find_name( NAME_IDENT, ph1id->type ), varid.buff() ); break; } case ISAKMP_ID_ASN1_DN: case ISAKMP_ID_ASN1_GN: { BDATA varid; asn1_text( ph1id->varid, varid ); varid.add( 0, 1 ); sprintf_s( text, LIBIKE_MAX_TEXTP1ID, "%s %s", find_name( NAME_IDENT, ph1id->type ), varid.buff() ); break; } case ISAKMP_ID_KEY_ID: { sprintf_s( text, LIBIKE_MAX_TEXTP1ID, "%s [ %lu bytes ]", find_name( NAME_IDENT, ph1id->type ), ph1id->varid.size() ); break; } default: sprintf_s( text, LIBIKE_MAX_TEXTP1ID, "" ); } } void _IKED::text_ph2id( char * text, IKE_PH2ID * ph2id ) { char txtprot[ LIBIKE_MAX_TEXTPROT ]; char txtaddr1[ LIBIKE_MAX_TEXTADDR ]; char txtaddr2[ LIBIKE_MAX_TEXTADDR ]; char txtport[ LIBIKE_MAX_TEXTPORT ]; switch( ph2id->type ) { case ISAKMP_ID_IPV4_ADDR: text_prot( txtprot, ph2id->prot ); text_addr( txtaddr1, ph2id->addr1 ); text_port( txtport, ph2id->port ); sprintf_s( text, LIBIKE_MAX_TEXTP2ID, "%s:%s:%s", txtprot, txtaddr1, txtport ); break; case ISAKMP_ID_IPV4_ADDR_SUBNET: text_prot( txtprot, ph2id->prot ); text_addr( txtaddr1, ph2id->addr1 ); text_mask( txtaddr2, ph2id->addr2 ); text_port( txtport, ph2id->port ); sprintf_s( text, LIBIKE_MAX_TEXTP2ID, "%s:%s/%s:%s", txtprot, txtaddr1, txtaddr2, txtport ); break; case ISAKMP_ID_IPV4_ADDR_RANGE: text_prot( txtprot, ph2id->prot ); text_addr( txtaddr1, ph2id->addr1 ); text_addr( txtaddr2, ph2id->addr2 ); text_port( txtport, ph2id->port ); sprintf_s( text, LIBIKE_MAX_TEXTP2ID, "%s:%s-%s:%s", txtprot, txtaddr1, txtaddr2, txtport ); break; default: sprintf_s( text, LIBIKE_MAX_TEXTP2ID, "" ); } } bool has_sockaddr( sockaddr * saddr ) { switch( saddr->sa_family ) { case AF_INET: { sockaddr_in * saddr_in = ( sockaddr_in * ) saddr; if( saddr_in->sin_addr.s_addr ) return true; } } return false; } bool cmp_sockaddr( sockaddr & saddr1, sockaddr & saddr2, bool port ) { if( saddr1.sa_family != saddr2.sa_family ) return false; switch( saddr1.sa_family ) { case AF_INET: { sockaddr_in * saddr1_in = ( sockaddr_in * ) &saddr1; sockaddr_in * saddr2_in = ( sockaddr_in * ) &saddr2; if( saddr1_in->sin_addr.s_addr != saddr2_in->sin_addr.s_addr ) return false; if( port ) if( saddr1_in->sin_port != saddr2_in->sin_port ) return false; return true; } } return false; } bool cpy_sockaddr( sockaddr & saddr1, sockaddr & saddr2, bool port ) { switch( saddr1.sa_family ) { case AF_INET: { sockaddr_in * saddr1_in = ( sockaddr_in * ) &saddr1; sockaddr_in * saddr2_in = ( sockaddr_in * ) &saddr2; SET_SALEN( saddr2_in, sizeof( sockaddr_in ) ); saddr2_in->sin_family = AF_INET; saddr2_in->sin_addr = saddr1_in->sin_addr; if( port ) saddr2_in->sin_port = saddr1_in->sin_port; else saddr2_in->sin_port = 0; return true; } } return false; } bool get_sockport( sockaddr & saddr, u_int16_t & port ) { switch( saddr.sa_family ) { case AF_INET: { sockaddr_in * saddr_in = ( sockaddr_in * ) &saddr; port = saddr_in->sin_port; return true; } } return false; } bool set_sockport( sockaddr & saddr, u_int16_t port ) { switch( saddr.sa_family ) { case AF_INET: { sockaddr_in * saddr_in = ( sockaddr_in * ) &saddr; saddr_in->sin_port = port; return true; } } return false; } bool cmp_ikeaddr( IKE_SADDR & addr1, IKE_SADDR & addr2, bool port ) { return cmp_sockaddr( addr1.saddr, addr2.saddr, port ); } ike-2.2.1+dfsg/source/iked/ike.packet.cpp000066400000000000000000000123451223036517100201460ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "iked.h" _PACKET_IKE::_PACKET_IKE() { reset(); memset( &header, 0, sizeof( header ) ); notify = 0; } _PACKET_IKE::~_PACKET_IKE() { reset(); } void _PACKET_IKE::reset() { size( 0 ); pld_depth = 0; } void _PACKET_IKE::set_msgid( uint32_t msgid ) { header.msgid = msgid; } uint32_t _PACKET_IKE::get_msgid() { return header.msgid; } bool _PACKET_IKE::write( IKE_COOKIES & cookies, uint8_t payload, uint8_t exchange, uint8_t flags ) { // reset packet data reset(); // define header information and add header.cookies = cookies; header.payload = payload; header.version = ISAKMP_VERSION; header.exchange = exchange; header.flags = flags; header.length = 0; add( &header, sizeof( header ) ); return true; } bool _PACKET_IKE::done() { header.length = ( uint32_t ) data_size; IKE_HEADER * tmp_header = ( IKE_HEADER * ) data_buff; tmp_header->length = htonl( header.length ); return true; } bool _PACKET_IKE::add_payload( bool encap, uint8_t next ) { // encapsulate payload if( encap ) pld_depth++; // store payload start pld_stack[ pld_depth ].oset = data_size; pld_stack[ pld_depth ].size = 0; // write payload header IKE_PAYLOAD payload; payload.next = next; payload.reserved = 0; payload.length = 0; return add( &payload, sizeof( payload ) ); } void _PACKET_IKE::end_payload( bool decap, bool write ) { short pld_oset = ( short ) pld_stack[ pld_depth ].oset; short pld_size = ( short ) data_size - pld_oset; // // write the payload params // in the packet // if( write ) { // set payload size in packet IKE_PAYLOAD * payload = ( IKE_PAYLOAD * )( data_buff + pld_oset ); payload->length = htons( pld_size ); // potentially add payload size // to the parent payload size if( pld_depth > 0 ) pld_stack[ pld_depth - 1 ].size += pld_size; } // decapsulate payload if( decap ) pld_depth--; } bool _PACKET_IKE::read( IKE_COOKIES & cookies, uint8_t & payload, uint8_t & exchange, uint8_t & flags ) { // reset packet read positions data_oset = 0; pld_depth = 0; // get and determine header information if( !get( &header, sizeof( header ) ) ) return false; header.length = ntohl( header.length ); cookies = header.cookies; payload = header.payload; exchange = header.exchange; flags = header.flags; return true; } bool _PACKET_IKE::get_payload( bool encap, uint8_t & next ) { // // check packet size for enough // data to contain a payload // if( ( data_oset + 4 ) > data_size ) return false; // encapsulate payload if( encap ) pld_depth++; // store payload start pld_stack[ pld_depth ].oset = data_oset; // read payload header IKE_PAYLOAD payload; if( !get( &payload, sizeof( payload ) ) ) return false; // store payload size pld_stack[ pld_depth ].size = ntohs( payload.length ); // store caller next payload type next = payload.next; return true; } size_t _PACKET_IKE::get_payload_left() { return pld_stack[ pld_depth ].oset + pld_stack[ pld_depth ].size - data_oset; } ike-2.2.1+dfsg/source/iked/ike.payload.cpp000066400000000000000000001121451223036517100203270ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "iked.h" long _IKED::payload_add_frag( PACKET_IKE & packet, unsigned char & index, unsigned char * data, size_t & size, size_t max ) { log.txt( LLOG_DEBUG, ">> : fragment payload\n" ); // // adjust the callers max to account for // the fragment header size // max -= 8; // // check if this will be the last fragment // and calculate the source packets offset // and size // unsigned char flags = 0; if( size <= max ) flags |= IKE_FRAG_FLAG_LAST; if( size > max ) size = max; // // sanity check size to make sure it doesn't // overflow the 16bit value // if( ( size + 8 ) > 0xFFFF ) { log.txt( LLOG_DEBUG, "!! : ike fragment length > 16bit\n" ); return LIBIKE_FAILED; } uint16_t total = ( uint16_t ) size + 8; // // write the fragment header // packet.add_word( 0 ); // always set to 0 ? packet.add_word( total ); packet.add_word( 1 ); // always set to 1 ? packet.add_byte( index ); packet.add_byte( flags ); // write the fragment data packet.add( data, size ); return LIBIKE_OK; } long _IKED::payload_get_frag( PACKET_IKE & packet, IDB_PH1 * ph1, bool & complete ) { log.txt( LLOG_DEBUG, "<< : fragment payload\n" ); // // read the frag payload header // uint16_t unknown; uint16_t size; uint8_t index; uint8_t flags; packet.get_word( unknown ); // always set to 0 ? packet.get_word( size ); packet.get_word( unknown ); // always set to 1 ? packet.get_byte( index ); packet.get_byte( flags ); // // adjust the size to take the // fragment header into account // size -= 8; // // perform some sanity check // size_t data_real = packet.size() - packet.oset(); if( data_real < size ) { log.txt( LLOG_ERROR, "!! : packet size is invalid for given fragment size\n" ); return LIBIKE_DECODE; } log.txt( LLOG_DEBUG, "ii : - frag index = %i\n" "ii : - frag size = %i\n", index, size ); // // add to our ph1 fragment list // ph1->frag_add( packet.buff() + packet.oset(), size, index, ( flags & IKE_FRAG_FLAG_LAST ) ); // // attempt to retrieve the complete packet // if( ph1->frag_get( packet ) ) complete = true; return LIBIKE_OK; } long _IKED::payload_add_attr( PACKET_IKE & packet, IKE_ATTR & attrib ) { if( attrib.basic ) { packet.add_word( BASIC | attrib.atype ); packet.add_word( attrib.bdata ); } else { packet.add_word( attrib.atype ); packet.add_word( short( attrib.vdata.size() ) ); packet.add( attrib.vdata ); } return LIBIKE_OK; } long _IKED::payload_get_attr( PACKET_IKE & packet, IKE_ATTR & attrib ) { // // get the attribute type // if( !packet.get_word( attrib.atype ) ) return LIBIKE_DECODE; // // determine if this is a // four byte attribute or a // variable lenth attribute // if( attrib.atype & BASIC ) { // // basic two byte attribute // attrib.atype &= ~BASIC; attrib.basic = true; if( !packet.get_word( attrib.bdata ) ) return LIBIKE_DECODE; } else { // // variable length attribute // uint16_t alen; if( !packet.get_word( alen ) ) return LIBIKE_DECODE; // // sanity check for packet data // if( ( packet.size() - packet.oset() ) > alen ) return LIBIKE_DECODE; // // read the variable length data // packet.get( attrib.vdata, alen ); } return LIBIKE_OK; } long _IKED::payload_add_sa( PACKET_IKE & packet, IDB_LIST_PROPOSAL & plist, uint8_t next ) { // // write security association payload // log.txt( LLOG_DEBUG, ">> : security association payload\n" ); packet.add_payload( false, next ); // ADD - sa packet.add_quad( ISAKMP_DOI_IPSEC ); // domain of interop packet.add_quad( ISAKMP_SIT_IDENT_ONLY ); // identity protect situation // // step through our proposal list // IKE_PROPOSAL * proposal; long pindex = 0; long tcount; long tindex; while( plist.nextp( &proposal, pindex, tindex, tcount ) ) { // // write proposal payload // log.txt( LLOG_DEBUG, ">> : - proposal #%i payload \n", proposal->pnumb ); next = ISAKMP_PAYLOAD_PROPOSAL; if( pindex == -1 ) next = ISAKMP_PAYLOAD_NONE; packet.add_payload( true, next ); // ADD - sa.proposal packet.add_byte( proposal->pnumb ); // proposal number packet.add_byte( proposal->proto ); // protocol type // // add spi data // switch( proposal->proto ) { case ISAKMP_PROTO_ISAKMP: packet.add_byte( 0 ); // spi size packet.add_byte( ( unsigned char ) tcount ); // number of transforms break; case ISAKMP_PROTO_IPSEC_AH: case ISAKMP_PROTO_IPSEC_ESP: packet.add_byte( ISAKMP_SPI_SIZE ); // spi size packet.add_byte( ( unsigned char ) tcount ); // number of transforms packet.add_quad( proposal->spi.spi, false ); // spi data break; case ISAKMP_PROTO_IPCOMP: packet.add_byte( ISAKMP_CPI_SIZE ); // spi size packet.add_byte( ( unsigned char ) tcount ); // number of transforms packet.add_word( proposal->spi.cpi, false ); // spi data break; } // // step through our transform list // while( plist.nextt( &proposal, tindex ) ) { // // add our transform // next = ISAKMP_PAYLOAD_TRANSFORM; if( tindex == - 1 ) next = ISAKMP_PAYLOAD_NONE; payload_add_xform( packet, proposal, next ); } packet.end_payload( true ); // END -> sa.proposal packet.end_payload( false ); // END -> sa } return LIBIKE_OK; } long _IKED::payload_get_sa( PACKET_IKE & packet, IDB_LIST_PROPOSAL & plist ) { log.txt( LLOG_DEBUG, "<< : security association payload\n" ); // // read security association packet // uint32_t doi; uint32_t sit; // // check domain of interpretation // packet.get_quad( doi ); if( doi != ISAKMP_DOI_IPSEC ) { log.txt( LLOG_ERROR, "!! : rejecting sa payload, invalid doi ( %i )\n", doi ); packet.notify = ISAKMP_N_DOI_NOT_SUPPORTED; return LIBIKE_FAILED; } // // check situation // packet.get_quad( sit ); if( doi != ISAKMP_SIT_IDENT_ONLY ) { log.txt( LLOG_ERROR, "!! : rejecting sa payload, invalid situation ( %i )\n", sit ); packet.notify = ISAKMP_N_SITUATION_NOT_SUPPORTED; return LIBIKE_FAILED; } // // read all proposal payloads // while( 1 ) { // // read next proposal payload // uint8_t next_proposal; if( !packet.get_payload( true, next_proposal ) ) return LIBIKE_DECODE; uint8_t pnumb; uint8_t proto; uint8_t xform_count = 0; uint8_t xform_index = 0; IKE_SPI spi; packet.get_byte( pnumb ); packet.get_byte( proto ); packet.get_byte( spi.size ); packet.get_byte( xform_count ); log.txt( LLOG_DEBUG, "<< : - propsal #%i payload \n", pnumb ); // // validate the protocol and spi // bool badspi = false; switch( proto ) { case ISAKMP_PROTO_ISAKMP: if( spi.size % ISAKMP_COOKIE_SIZE ) badspi = true; else packet.get_null( spi.size ); break; case ISAKMP_PROTO_IPSEC_AH: case ISAKMP_PROTO_IPSEC_ESP: if( spi.size != ISAKMP_SPI_SIZE ) badspi = true; else packet.get_quad( spi.spi, false ); break; case ISAKMP_PROTO_IPCOMP: if( spi.size != ISAKMP_CPI_SIZE ) badspi = true; else packet.get_word( spi.cpi, false ); break; default: log.txt( LLOG_ERROR, "\n" "!! : rejecting sa payload\n" "!! : invalid protocol %s ( %i ) \n" "\n", find_name( NAME_PROTOCOL, proto ), proto ); packet.notify = ISAKMP_N_INVALID_PROTOCOL_ID; return LIBIKE_FAILED; } if( badspi ) { log.txt( LLOG_ERROR, "!! : invalid spi size of %i for protocol %s \n", spi.size, find_name( NAME_PROTOCOL, proto ) ); packet.notify = ISAKMP_N_INVALID_SPI; return LIBIKE_FAILED; } // // read all transforms // for( ; xform_index < xform_count; xform_index++ ) { IKE_PROPOSAL transform; memset( &transform, 0, sizeof( transform ) ); transform.pnumb = pnumb; transform.proto = proto; transform.spi = spi; long result = payload_get_xform( packet, &transform ); if( result != LIBIKE_OK ) return result; plist.add( &transform, !xform_index ); } // // end proposal // packet.end_payload( true, false ); // // stop if last proposal // if( !next_proposal ) break; } // // end sa payload // return LIBIKE_OK; } long _IKED::payload_add_xform( PACKET_IKE & packet, IKE_PROPOSAL * proposal, uint8_t next ) { // // write transform payload // log.txt( LLOG_DEBUG, ">> : -- transform #%i payload \n", proposal->tnumb ); packet.add_payload( true, next ); // ADD -> sa.proposal.transform packet.add_byte( proposal->tnumb ); // transform number packet.add_byte( proposal->xform ); // transform type packet.add_word( 0 ); // reserved // write attributes based on protocol // type ( phase1 or phase2 ) // switch( proposal->proto ) { // // phase1 attributes // case ISAKMP_PROTO_ISAKMP: { packet.add_word( BASIC | IKE_ATTR_TRANSFORM ); // A - transform algorithm packet.add_word( proposal->ciph_id ); // V - algorithm id if( proposal->ciph_kl ) { packet.add_word( BASIC | IKE_ATTR_KEY_LENGTH ); // A - transform key length packet.add_word( proposal->ciph_kl ); // V - key length value } packet.add_word( BASIC | IKE_ATTR_HASH ); // A - hash algorithm packet.add_word( proposal->hash_id ); // V - algorithm id packet.add_word( BASIC | IKE_ATTR_GROUP_DESC ); // A - group description packet.add_word( proposal->dhgr_id ); // V - description id packet.add_word( BASIC | IKE_ATTR_AUTH_METHOD ); // A - authentication method packet.add_word( proposal->auth_id ); // V - method id if( proposal->life_sec ) { packet.add_word( BASIC | IKE_ATTR_LIFE_TYPE ); // A - life type packet.add_word( IKE_LIFE_TYPE_SECONDS ); // V - in seconds packet.add_word( IKE_ATTR_LIFE_DURATION ); // A - life duration packet.add_word( 4 ); // L - value length packet.add_quad( proposal->life_sec ); // V - number of seconds } if( proposal->life_kbs ) { packet.add_word( BASIC | IKE_ATTR_LIFE_TYPE ); // A - life type packet.add_word( IKE_LIFE_TYPE_KBYTES ); // V - in seconds packet.add_word( IKE_ATTR_LIFE_DURATION ); // A - life duration packet.add_word( 4 ); // L - value length packet.add_quad( proposal->life_kbs ); // V - number of seconds } break; } // // phase2 attributes // case ISAKMP_PROTO_IPSEC_AH: case ISAKMP_PROTO_IPSEC_ESP: case ISAKMP_PROTO_IPCOMP: { packet.add_word( BASIC | ISAKMP_ATTR_ENCAP_MODE ); // A - encapsulation method packet.add_word( proposal->encap ); // V - method id if( proposal->ciph_kl ) { // // only for ciphers with // variable length keys // packet.add_word( BASIC | ISAKMP_ATTR_KEY_LEGTH ); // A - transform key length packet.add_word( proposal->ciph_kl ); // V - key length value } if( proposal->hash_id ) { packet.add_word( BASIC | ISAKMP_ATTR_AUTH_ALGORITHM ); // A - authentication method packet.add_word( proposal->hash_id ); // V - algorithm id } if( proposal->dhgr_id ) { // // only for transforms which // require a pfs group // packet.add_word( BASIC | ISAKMP_ATTR_GROUP_DESC ); // A - group description packet.add_word( proposal->dhgr_id ); // V - description id } if( proposal->life_sec ) { packet.add_word( BASIC | ISAKMP_ATTR_LIFE_TYPE ); // A - life type packet.add_word( ISAKMP_LIFETYPE_SECONDS ); // V - in seconds packet.add_word( ISAKMP_ATTR_LIFE_DURATION ); // A - life duration packet.add_word( 4 ); // L - value length packet.add_quad( proposal->life_sec ); // V - number of seconds } if( proposal->life_kbs ) { packet.add_word( BASIC | ISAKMP_ATTR_LIFE_TYPE ); // A - life type packet.add_word( ISAKMP_LIFETYPE_KBYTES ); // V - in seconds packet.add_word( ISAKMP_ATTR_LIFE_DURATION ); // A - life duration packet.add_word( 4 ); // L - value length packet.add_quad( proposal->life_kbs ); // V - number of seconds } break; } default: log.txt( LLOG_ERROR, "!! : invalid protocol in proposal" ); return LIBIKE_FAILED; } packet.end_payload( true ); // END -> sa.proposal.transform return LIBIKE_OK; } long _IKED::payload_get_xform( PACKET_IKE & packet, IKE_PROPOSAL * proposal ) { // // read next transform payload // uint8_t next; packet.get_payload( true, next ); uint16_t reserved; packet.get_byte( proposal->tnumb ); // transform number packet.get_byte( proposal->xform ); // transform type packet.get_word( reserved ); // reserved 2 bytes log.txt( LLOG_DEBUG, "<< : -- transform #%i payload \n", proposal->tnumb ); // // validate the transform type // bool valid = false; switch( proposal->proto ) { case ISAKMP_PROTO_ISAKMP: switch( proposal->xform ) { case ISAKMP_KEY_IKE: valid = true; break; } break; case ISAKMP_PROTO_IPSEC_ESP: switch( proposal->xform ) { case ISAKMP_ESP_DES: case ISAKMP_ESP_3DES: case ISAKMP_ESP_AES: case ISAKMP_ESP_BLOWFISH: case ISAKMP_ESP_CAST: valid = true; break; } break; case ISAKMP_PROTO_IPCOMP: switch( proposal->xform ) { case ISAKMP_IPCOMP_DEFLATE: case ISAKMP_IPCOMP_LZS: valid = true; break; } break; } size_t size = packet.get_payload_left(); uint32_t lvalue = 0; uint16_t svalue = 0; uint16_t ltype = 0; while( size ) { uint16_t attrib; uint16_t length; // // get the attribute type // packet.get_word( attrib ); // // determine if this is a // four byte attribute or a // variable lenth attribute // if( attrib & BASIC ) { // // basic four byte attribute // attrib &= ~BASIC; packet.get_word( svalue ); lvalue = svalue; } else { // // variable length attribute // packet.get_word( length ); // // the only attributes we understand are // two or four bytes long so reject any // values that are longer // switch( length ) { case 2: packet.get_word( svalue ); lvalue = svalue; break; case 4: packet.get_quad( lvalue ); break; } } // // read attributes based on protocol // switch( proposal->proto ) { // // phase1 attributes // case ISAKMP_PROTO_ISAKMP: { // // read all attribute / value pairs // switch( attrib ) { case IKE_ATTR_TRANSFORM: proposal->ciph_id = svalue; break; case IKE_ATTR_KEY_LENGTH: proposal->ciph_kl = svalue; break; case IKE_ATTR_HASH: proposal->hash_id = svalue; break; case IKE_ATTR_GROUP_DESC: proposal->dhgr_id = svalue; break; case IKE_ATTR_AUTH_METHOD: proposal->auth_id = svalue; break; case IKE_ATTR_LIFE_TYPE: ltype = svalue; break; case IKE_ATTR_LIFE_DURATION: { switch( ltype ) { case IKE_LIFE_TYPE_SECONDS: proposal->life_sec = lvalue; break; case IKE_LIFE_TYPE_KBYTES: proposal->life_kbs = lvalue; break; default: log.txt( LLOG_ERROR, "\n" "!! : rejecting phase1 proposal\n" "!! : unhandled life type ( %i )\n" "\n", ltype ); packet.notify = ISAKMP_N_BAD_PROPOSAL_SYNTAX; return LIBIKE_DECODE; } break; } default: { log.txt( LLOG_ERROR, "\n" "!! : rejecting phase1 proposal\n" "!! : unhandled attribute type ( %i )\n" "\n", attrib ); packet.notify = ISAKMP_N_ATTRIBUTES_NOT_SUPPORTED; return LIBIKE_DECODE; } } break; } // // phase2 attributes // case ISAKMP_PROTO_IPSEC_AH: case ISAKMP_PROTO_IPSEC_ESP: case ISAKMP_PROTO_IPCOMP: { // // read all attribute / value pairs // switch( attrib ) { case ISAKMP_ATTR_LIFE_TYPE: ltype = svalue; break; case ISAKMP_ATTR_LIFE_DURATION: { switch( ltype ) { case ISAKMP_LIFETYPE_SECONDS: proposal->life_sec = lvalue; break; case ISAKMP_LIFETYPE_KBYTES: proposal->life_kbs = lvalue; break; default: log.txt( LLOG_ERROR, "\n" "!! : rejecting phase2 proposal\n" "!! : unhandled life type ( %i )\n" "\n", ltype ); packet.notify = ISAKMP_N_BAD_PROPOSAL_SYNTAX; return LIBIKE_DECODE; } break; } case ISAKMP_ATTR_GROUP_DESC: proposal->dhgr_id = svalue; break; case ISAKMP_ATTR_ENCAP_MODE: proposal->encap = svalue; break; case ISAKMP_ATTR_AUTH_ALGORITHM: proposal->hash_id = svalue; break; case ISAKMP_ATTR_KEY_LEGTH: proposal->ciph_kl = svalue; break; default: { log.txt( LLOG_ERROR, "\n" "!! : rejecting phase2 proposal\n" "!! : unhandled attribute type ( %i )\n" "\n", attrib ); packet.notify = ISAKMP_N_ATTRIBUTES_NOT_SUPPORTED; return LIBIKE_DECODE; } } break; } } size = packet.get_payload_left(); } // // end transform // packet.end_payload( true, false ); return LIBIKE_OK; } long _IKED::payload_add_kex( PACKET_IKE & packet, BDATA & gx, uint8_t next ) { log.txt( LLOG_DEBUG, ">> : key exchange payload\n" ); // // write key exchange payload // packet.add_payload( false, next ); // ADD -> kex packet.add( gx ); // public value packet.end_payload( false ); // END -> kex return LIBIKE_OK; } long _IKED::payload_get_kex( PACKET_IKE & packet, BDATA & gx ) { log.txt( LLOG_DEBUG, "<< : key exchange payload\n" ); // // read key exchange payload // size_t size = packet.get_payload_left(); if( size > LIBIKE_MAX_DHGRP ) { log.txt( LLOG_ERROR, "<< : invalid dh size ( %i > %i )\n", size, LIBIKE_MAX_DHGRP ); packet.notify = ISAKMP_N_INVALID_HASH_INFORMATION; return LIBIKE_DECODE; } packet.get( gx, size ); return LIBIKE_OK; } long _IKED::payload_add_nonce( PACKET_IKE & packet, BDATA & nonce, uint8_t next ) { log.txt( LLOG_DEBUG, ">> : nonce payload\n" ); // // write nonce payload // packet.add_payload( false, next ); // ADD -> nonce packet.add( nonce ); // nonce value packet.end_payload( false ); // END -> nonce return LIBIKE_OK; } long _IKED::payload_get_nonce( PACKET_IKE & packet, BDATA & nonce ) { log.txt( LLOG_DEBUG, "<< : nonce payload\n" ); // // read nonce payload // size_t size = packet.get_payload_left(); if( ( size < ISAKMP_NONCE_MIN ) || ( size > ISAKMP_NONCE_MAX ) ) return LIBIKE_FAILED; packet.get( nonce, size ); // nonce value return LIBIKE_OK; } long _IKED::payload_add_ph1id( PACKET_IKE & packet, IKE_PH1ID & ph1id, uint8_t next ) { log.txt( LLOG_DEBUG, ">> : identification payload\n" ); // // write identity payload // packet.add_payload( false, next ); // ADD - identity packet.add_byte( ph1id.type ); // id type packet.add_byte( 0 ); // protocol ( ignore ) packet.add_word( 0 ); // IP port ( ignore ) switch( ph1id.type ) { case ISAKMP_ID_NONE: // // used for hybrid auth // break; case ISAKMP_ID_FQDN: case ISAKMP_ID_USER_FQDN: case ISAKMP_ID_ASN1_DN: case ISAKMP_ID_ASN1_GN: case ISAKMP_ID_KEY_ID: packet.add( ph1id.varid ); // string ids break; case ISAKMP_ID_IPV4_ADDR: packet.add_quad( ph1id.addr.s_addr, false ); // host address break; default: log.txt( LLOG_ERROR, "!! : unhandled phase1 id type \'%s\'( %i )\n", find_name( NAME_IDENT, ph1id.type ), ph1id.type ); return LIBIKE_ENCODE; } packet.end_payload( false, true ); // END - identity return LIBIKE_OK; } long _IKED::payload_get_ph1id( PACKET_IKE & packet, IKE_PH1ID & ph1id ) { log.txt( LLOG_DEBUG, "<< : identification payload\n" ); // // read responder identity payload // uint8_t r_prot; uint16_t r_port; uint32_t temp = 0; size_t size; packet.get_byte( ph1id.type ); // id type packet.get_byte( r_prot ); // protocol ( ignore ) packet.get_word( r_port ); // IP port ( ignore ) switch( ph1id.type ) { case ISAKMP_ID_NONE: // // used for hybrid auth // break; case ISAKMP_ID_FQDN: case ISAKMP_ID_USER_FQDN: case ISAKMP_ID_ASN1_DN: case ISAKMP_ID_ASN1_GN: case ISAKMP_ID_KEY_ID: size = packet.get_payload_left(); if( size < LIBIKE_MAX_VARID ) packet.get( ph1id.varid, size ); // string ids break; case ISAKMP_ID_IPV4_ADDR: packet.get_quad( temp, false ); // host address break; default: log.txt( LLOG_ERROR, "!! : unhandled phase1 id type \'%s\'( %i )\n", find_name( NAME_IDENT, ph1id.type ), ph1id.type ); packet.notify = ISAKMP_N_INVALID_ID_INFORMATION; return LIBIKE_DECODE; } ph1id.addr.s_addr = temp; return LIBIKE_OK; } long _IKED::payload_add_ph2id( PACKET_IKE & packet, IKE_PH2ID & ph2id, uint8_t next ) { log.txt( LLOG_DEBUG, ">> : identification payload\n" ); // // write identity payload // packet.add_payload( false, next ); // ADD - identity packet.add_byte( ph2id.type ); // id type packet.add_byte( ph2id.prot ); // protocol packet.add_word( ph2id.port, false ); // IP port switch( ph2id.type ) { case ISAKMP_ID_IPV4_ADDR: packet.add_quad( ph2id.addr1.s_addr, false ); // host address break; case ISAKMP_ID_IPV4_ADDR_RANGE: case ISAKMP_ID_IPV4_ADDR_SUBNET: packet.add_quad( ph2id.addr1.s_addr, false ); // address range / subnet packet.add_quad( ph2id.addr2.s_addr, false ); // address range / subnet mask break; default: log.txt( LLOG_ERROR, "!! : unhandled ipv4 id type \'%s\'( %i )\n", find_name( NAME_IDENT, ph2id.type ), ph2id.type ); return LIBIKE_ENCODE; } packet.end_payload( false, true ); // END - identity return LIBIKE_OK; } long _IKED::payload_get_ph2id( PACKET_IKE & packet, IKE_PH2ID & ph2id ) { log.txt( LLOG_DEBUG, "<< : identification payload\n" ); // // read responder identity payload // uint32_t temp1 = 0; uint32_t temp2 = 0; packet.get_byte( ph2id.type ); // id type packet.get_byte( ph2id.prot ); // protocol packet.get_word( ph2id.port, false ); // IP port switch( ph2id.type ) { case ISAKMP_ID_IPV4_ADDR: packet.get_quad( temp1, false ); // host address break; case ISAKMP_ID_IPV4_ADDR_RANGE: case ISAKMP_ID_IPV4_ADDR_SUBNET: packet.get_quad( temp1, false ); // address range / subnet packet.get_quad( temp2, false ); // address range / subnet mask break; default: log.txt( LLOG_ERROR, "!! : unhandled ipv4 id type \'%s\'( %i )\n", find_name( NAME_IDENT, ph2id.type ), ph2id.type ); packet.notify = ISAKMP_N_INVALID_ID_INFORMATION; return LIBIKE_DECODE; } ph2id.addr1.s_addr = temp1; ph2id.addr2.s_addr = temp2; return LIBIKE_OK; } long _IKED::payload_add_cert( PACKET_IKE & packet, uint8_t type, BDATA & cert, uint8_t next ) { log.txt( LLOG_DEBUG, ">> : certificate payload\n" ); // // write certificate payload // packet.add_payload( false, next ); // ADD - certificate packet.add_byte( type ); // certificate type packet.add( cert ); // certificate data packet.end_payload( false ); // END - certificate return LIBIKE_OK; } long _IKED::payload_get_cert( PACKET_IKE & packet, uint8_t & type, BDATA & cert ) { log.txt( LLOG_DEBUG, "<< : certificate payload\n" ); // // read certificate payload // size_t size = packet.get_payload_left(); size--; if( size > ISAKMP_CERT_MAX ) { log.txt( LLOG_ERROR, "!! : invalid certificate size ( %i > %i )\n", size, ISAKMP_CERT_MAX ); packet.notify = ISAKMP_N_PAYLOAD_MALFORMED; return LIBIKE_DECODE; } packet.get_byte( type ); // certificate type // // check certificate type // if( type == ISAKMP_CERT_X509_SIG ) packet.get( cert, size ); // certificate data else packet.get_null( size ); // certificate data return LIBIKE_OK; } long _IKED::payload_add_creq( PACKET_IKE & packet, uint8_t type, uint8_t next ) { log.txt( LLOG_DEBUG, ">> : cert request payload\n" ); // // write certificate request payload // packet.add_payload( false, next ); // ADD - certificate packet.add_byte( type ); // certificate request data packet.end_payload( false ); // END - certificate return LIBIKE_OK; } long _IKED::payload_get_creq( PACKET_IKE & packet, uint8_t & type, BDATA & dn ) { log.txt( LLOG_DEBUG, "<< : cert request payload\n" ); // // read certificate request payload // size_t size = packet.get_payload_left(); size--; if( size > ISAKMP_CREQ_MAX ) { log.txt( LLOG_ERROR, "!! : invalid certificate request size ( %i > %i )\n", size, ISAKMP_CREQ_MAX ); packet.notify = ISAKMP_N_PAYLOAD_MALFORMED; return LIBIKE_DECODE; } packet.get_byte( type ); // certificate request type packet.get( dn, size ); // certificate request dn data // // check certificate type // // if( type != ISAKMP_CERT_X509_SIG ) // { // packet.notify = ISAKMP_N_CERT_TYPE_UNSUPPORTED; // return LIBIKE_DECODE; // } return LIBIKE_OK; } long _IKED::payload_add_sign( PACKET_IKE & packet, BDATA & sign, uint8_t next ) { log.txt( LLOG_DEBUG, ">> : signature payload\n" ); // // write signature payload // packet.add_payload( false, next ); // ADD - signature packet.add( sign ); // signature data packet.end_payload( false ); // END - signature return LIBIKE_OK; } long _IKED::payload_get_sign( PACKET_IKE & packet, BDATA & sign ) { log.txt( LLOG_DEBUG, "<< : signature payload\n" ); // // read signature payload // size_t size = packet.get_payload_left(); if( size > ISAKMP_SIGN_MAX ) { log.txt( LLOG_ERROR, "!! : invalid signature payload size ( %i > %i )\n", size, ISAKMP_SIGN_MAX ); packet.notify = ISAKMP_N_PAYLOAD_MALFORMED; return LIBIKE_DECODE; } packet.get( sign, size ); // signature data return LIBIKE_OK; } long _IKED::payload_add_hash( PACKET_IKE & packet, BDATA & hash, uint8_t next ) { log.txt( LLOG_DEBUG, ">> : hash payload\n" ); // // write hash payload // packet.add_payload( false, next ); // ADD - hash packet.add( hash ); // hash value packet.end_payload( false ); // END - hash return LIBIKE_OK; } long _IKED::payload_get_hash( PACKET_IKE & packet, BDATA & hash, long hash_size ) { log.txt( LLOG_DEBUG, "<< : hash payload\n" ); // // read hash payload // size_t size = packet.get_payload_left(); if( size != hash_size ) { log.txt( LLOG_ERROR, "!! : invalid hash size ( %i != %i )\n", size, hash_size ); packet.notify = ISAKMP_N_INVALID_HASH_INFORMATION; return LIBIKE_DECODE; } packet.get( hash, size ); // hash value return LIBIKE_OK; } long _IKED::payload_add_vend( PACKET_IKE & packet, BDATA & vend, uint8_t next ) { log.txt( LLOG_DEBUG, ">> : vendor id payload\n" ); // // write vendor id payload // packet.add_payload( false, next ); packet.add( vend ); packet.end_payload( false ); return LIBIKE_OK; } long _IKED::payload_get_vend( PACKET_IKE & packet, BDATA & vend ) { log.txt( LLOG_DEBUG, "<< : vendor id payload\n" ); // // read vendor id payload // size_t size = packet.get_payload_left(); // // if the vendor id is greater // than our max allowable vend // id size, skip it as we wont // recognize it anyway // if( size <= ISAKMP_SIGN_MAX ) packet.get( vend, size ); else packet.get_null( size ); return LIBIKE_OK; } long _IKED::payload_add_cfglist( PACKET_IKE & packet, IDB_CFG * cfg, uint8_t next ) { log.txt( LLOG_DEBUG, ">> : attribute payload\n" ); // // write attribute payload // packet.add_payload( false, next ); packet.add_byte( cfg->mtype ); // message type packet.add_byte( 0 ); // reserved packet.add_word( cfg->ident ); // identity long count = cfg->attr_count(); long index = 0; for( ; index < count; index++ ) { IKE_ATTR * attr = cfg->attr_get( index ); if( attr->basic ) { packet.add_word( BASIC | attr->atype ); packet.add_word( attr->bdata ); } else { packet.add_word( attr->atype ); packet.add_word( short( attr->vdata.size() ) ); packet.add( attr->vdata ); } } packet.end_payload( false ); return LIBIKE_OK; } long _IKED::payload_get_cfglist( PACKET_IKE & packet, IDB_CFG * cfg ) { log.txt( LLOG_DEBUG, "<< : attribute payload\n" ); // // read attribute payload // packet.get_byte( cfg->mtype ); // message type packet.get_null( 1 ); // reserved packet.get_word( cfg->ident ); // identity // // get remaining payload length // size_t size = packet.get_payload_left(); while( size ) { // // get the attribute type // uint16_t atype; packet.get_word( atype ); // // determine if this is a // four byte attribute or a // variable lenth attribute // if( atype & BASIC ) { // // basic two byte attribute // uint16_t adata; packet.get_word( adata ); cfg->attr_add_b( atype & ~BASIC, adata ); } else { // // variable length attribute // uint16_t asize; BDATA adata; packet.get_word( asize ); packet.get( adata, asize ); cfg->attr_add_v( atype, adata.buff(), adata.size() ); } // // get remaining payload length // size = packet.get_payload_left(); } return LIBIKE_OK; } long _IKED::payload_add_natd( PACKET_IKE & packet, BDATA & natd, uint8_t next ) { log.txt( LLOG_DEBUG, ">> : nat discovery payload\n" ); // // write natd hash payload // packet.add_payload( false, next ); // ADD - hash packet.add( natd ); // hash value packet.end_payload( false ); // END - hash return LIBIKE_OK; } long _IKED::payload_get_natd( PACKET_IKE & packet, BDATA & natd, long natd_size ) { log.txt( LLOG_DEBUG, "<< : nat discovery payload\n" ); // // read hash payload // size_t size = packet.get_payload_left(); if( size != natd_size ) { log.txt( LLOG_ERROR, "!! : invalid natd hash size ( %i != %i )\n", size, natd_size ); packet.notify = ISAKMP_N_INVALID_HASH_INFORMATION; return LIBIKE_DECODE; } packet.get( natd, size ); // hash value return LIBIKE_OK; } long _IKED::payload_add_notify( PACKET_IKE & packet, IKE_NOTIFY * notify, uint8_t next ) { log.txt( LLOG_DEBUG, ">> : notification payload\n" ); // // write notification payload // packet.add_payload( false, next ); packet.add_quad( notify->doi ); packet.add_byte( notify->proto ); packet.add_byte( notify->spi.size ); packet.add_word( notify->code ); switch( notify->spi.size ) { case ( ISAKMP_COOKIE_SIZE * 2 ): packet.add( notify->spi.cookies.i, ISAKMP_COOKIE_SIZE ); packet.add( notify->spi.cookies.r, ISAKMP_COOKIE_SIZE ); break; case ISAKMP_SPI_SIZE: packet.add_quad( notify->spi.spi, false ); break; case ISAKMP_CPI_SIZE: packet.add_word( notify->spi.cpi, false ); break; } // // write any extra notify data // packet.add( notify->data ); packet.end_payload( false ); return LIBIKE_OK; } long _IKED::payload_get_notify( PACKET_IKE & packet, IKE_NOTIFY * notify ) { log.txt( LLOG_DEBUG, "<< : notification payload\n" ); // // read notification payload // notify->type = ISAKMP_PAYLOAD_NOTIFY; packet.get_quad( notify->doi ); packet.get_byte( notify->proto ); packet.get_byte( notify->spi.size ); packet.get_word( notify->code ); // // read the spi // switch( notify->spi.size ) { case 0: break; case ( ISAKMP_COOKIE_SIZE * 2 ): packet.get( notify->spi.cookies.i, ISAKMP_COOKIE_SIZE ); packet.get( notify->spi.cookies.r, ISAKMP_COOKIE_SIZE ); break; case ISAKMP_SPI_SIZE: packet.get_quad( notify->spi.spi, false ); break; case ISAKMP_CPI_SIZE: packet.get_word( notify->spi.cpi, false ); break; default: log.txt( LLOG_ERROR, "<< : notification payload contained invalid spi\n" ); return LIBIKE_FAILED; } // // read any extra notify data // size_t size = packet.get_payload_left(); packet.get( notify->data, size ); return LIBIKE_OK; } long _IKED::payload_add_delete( PACKET_IKE & packet, IKE_NOTIFY * notify, uint8_t next ) { log.txt( LLOG_DEBUG, ">> : delete payload\n" ); // // write delete payload // packet.add_payload( false, next ); packet.add_quad( notify->doi ); packet.add_byte( notify->proto ); packet.add_byte( notify->spi.size ); packet.add_word( 1 ); switch( notify->spi.size ) { case ( ISAKMP_COOKIE_SIZE * 2 ): packet.add( notify->spi.cookies.i, ISAKMP_COOKIE_SIZE ); packet.add( notify->spi.cookies.r, ISAKMP_COOKIE_SIZE ); break; case ISAKMP_SPI_SIZE: packet.add_quad( notify->spi.spi, false ); break; case ISAKMP_CPI_SIZE: packet.add_word( notify->spi.cpi, false ); break; } packet.end_payload( false ); return LIBIKE_OK; } long _IKED::payload_get_delete( PACKET_IKE & packet, IKE_NOTIFY * notify ) { log.txt( LLOG_DEBUG, "<< : delete payload\n" ); // // read notification payload // uint16_t spi_count; notify->type = ISAKMP_PAYLOAD_DELETE; packet.get_quad( notify->doi ); packet.get_byte( notify->proto ); packet.get_byte( notify->spi.size ); // // TODO : deal with multiple spi's // packet.get_word( spi_count ); switch( notify->spi.size ) { case 0: break; case ( ISAKMP_COOKIE_SIZE * 2 ): packet.get( notify->spi.cookies.i, ISAKMP_COOKIE_SIZE ); packet.get( notify->spi.cookies.r, ISAKMP_COOKIE_SIZE ); break; case ISAKMP_SPI_SIZE: packet.get_quad( notify->spi.spi, false ); break; case ISAKMP_CPI_SIZE: packet.get_word( notify->spi.cpi, false ); break; default: log.txt( LLOG_ERROR, "<< : notification payload contained invalid spi\n" ); return LIBIKE_FAILED; } return LIBIKE_OK; } ike-2.2.1+dfsg/source/iked/ike.peerid.cpp000066400000000000000000000244521223036517100201510ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "iked.h" bool _IKED::gen_ph1id_l( IDB_PH1 * ph1, IKE_PH1ID & ph1id ) { ph1id.type = ph1->tunnel->peer->idtype_l; switch( ph1id.type ) { case ISAKMP_ID_NONE: break; case ISAKMP_ID_ASN1_DN: { if( ph1->tunnel->peer->iddata_l.size() ) { if( !text_asn1( ph1->tunnel->peer->iddata_l, ph1id.varid ) ) { BDATA temp; temp = ph1->tunnel->peer->iddata_l; temp.add( "", 1 ); log.txt( LLOG_ERROR, "!! : failed to generate local %s id from \'%s\'\n", find_name( NAME_IDENT, ph1id.type ), temp.text() ); return false; } } else { cert_subj( ph1->tunnel->peer->cert_l, ph1id.varid ); } break; } case ISAKMP_ID_IPV4_ADDR: { if( ph1->tunnel->peer->iddata_l.size() ) { BDATA temp; temp = ph1->tunnel->peer->iddata_l; temp.add( "", 1 ); ph1id.addr.s_addr = inet_addr( temp.text() ); if( ph1id.addr.s_addr == INADDR_NONE ) { log.txt( LLOG_ERROR, "!! : failed to generate local %s id from \'%s\'\n", find_name( NAME_IDENT, ph1id.type ), temp.text() ); return false; } } else { ph1id.addr.s_addr = ph1->tunnel->saddr_l.saddr4.sin_addr.s_addr; } break; } case ISAKMP_ID_FQDN: case ISAKMP_ID_USER_FQDN: case ISAKMP_ID_KEY_ID: { ph1id.varid.set( ph1->tunnel->peer->iddata_l ); break; } default: { log.txt( LLOG_ERROR, "!! : failed to generate local id for unknown type %i\n", ph1id.type ); return false; } } return true; } bool _IKED::gen_ph1id_r( IDB_PH1 * ph1, IKE_PH1ID & ph1id ) { ph1id.type = ph1->tunnel->peer->idtype_r; switch( ph1id.type ) { case ISAKMP_ID_NONE: break; case ISAKMP_ID_ASN1_DN: { if( ph1->tunnel->peer->iddata_r.size() ) { if( !text_asn1( ph1->tunnel->peer->iddata_r, ph1id.varid ) ) { BDATA temp; temp = ph1->tunnel->peer->iddata_r; temp.add( "", 1 ); log.txt( LLOG_ERROR, "!! : failed to generate remote %s id from \'%s\'\n", find_name( NAME_IDENT, ph1id.type ), temp.text() ); return false; } } break; } case ISAKMP_ID_IPV4_ADDR: { if( ph1->tunnel->peer->iddata_r.size() ) { BDATA temp; temp = ph1->tunnel->peer->iddata_r; temp.add( "", 1 ); ph1id.addr.s_addr = inet_addr( temp.text() ); if( ph1id.addr.s_addr == INADDR_NONE ) { log.txt( LLOG_ERROR, "!! : failed to generate remote %s id from \'%s\'\n", find_name( NAME_IDENT, ph1id.type ), temp.text() ); return false; } } else { ph1id.addr.s_addr = ph1->tunnel->saddr_r.saddr4.sin_addr.s_addr; } break; } case ISAKMP_ID_FQDN: case ISAKMP_ID_USER_FQDN: case ISAKMP_ID_KEY_ID: { ph1id.varid.set( ph1->tunnel->peer->iddata_r ); break; } default: { log.txt( LLOG_ERROR, "!! : failed to generate remote id for unknown type %i\n", ph1id.type ); return false; } } return true; } bool _IKED::cmp_ph1id( IKE_PH1ID & idt, IKE_PH1ID & ids, bool natt ) { static const char * expl_natt = "( natt prevents ip match )"; static const char * expl_cert = "( cert check only )"; static const char * expl_none = ""; const char * expl = expl_none; // // compare the peer id received // with our generated peer id // if( ( ids.type != idt.type ) && ( idt.type != ISAKMP_ID_NONE ) ) { log.txt( LLOG_ERROR, "!! : phase1 id type mismatch ( received %s but expected %s )\n", find_name( NAME_IDENT, ids.type ), find_name( NAME_IDENT, idt.type ) ); return false; } // // match the id value // bool match = true; switch( idt.type ) { case ISAKMP_ID_NONE: log.txt( LLOG_INFO, "ii : phase1 id target is any\n" ); break; case ISAKMP_ID_IPV4_ADDR: { if( natt ) expl = expl_natt; else if( ids.addr.s_addr != idt.addr.s_addr ) match = false; break; } case ISAKMP_ID_FQDN: case ISAKMP_ID_USER_FQDN: case ISAKMP_ID_KEY_ID: { ids.varid.add( 0, 1 ); idt.varid.add( 0, 1 ); if( ids.varid != idt.varid ) match = false; break; } case ISAKMP_ID_ASN1_DN: case ISAKMP_ID_ASN1_GN: { // // if we have a specific name // to comapre against, check // it now. otherwise only use // the id to verify the cert // subject // if( idt.varid.size() ) { BDATA idts; BDATA idtt; asn1_text( ids.varid, idts ); asn1_text( idt.varid, idtt ); idts.add( 0, 1 ); idtt.add( 0, 1 ); if( idts != idtt ) match = false; } else expl = expl_cert; break; } default: { log.txt( LLOG_ERROR, "!! : phase1 id mismatch ( internal error )\n" ); return false; } } if( match ) { // // generate text id for logging // char txtid[ LIBIKE_MAX_TEXTP1ID ]; text_ph1id( txtid, &ids ); log.txt( LLOG_INFO, "ii : phase1 id match %s\n" "ii : received = %s\n", expl, txtid ); } else { // // generate text ids for logging // char txtid_s[ LIBIKE_MAX_TEXTP1ID ]; text_ph1id( txtid_s, &ids ); char txtid_t[ LIBIKE_MAX_TEXTP1ID ]; text_ph1id( txtid_t, &idt ); log.txt( LLOG_ERROR, "!! : phase1 id mismatch %s\n" "!! : received = %s\n" "!! : expected = %s\n", expl, txtid_s, txtid_t ); } return match; } bool _IKED::cmp_ph2id( IKE_PH2ID & idt, IKE_PH2ID & ids, bool exact ) { // // exact match option enforces // like id value types // if( exact ) if( ids.type != idt.type ) return false; // // compare protocol value // if( ids.prot != idt.prot ) return false; // // compare port value // if( ids.port != idt.port ) return false; // // inclusive match // switch( ids.type ) { case ISAKMP_ID_NONE: { // // anything to ... // return true; } case ISAKMP_ID_IPV4_ADDR: { switch( idt.type ) { // // ipv4 address to ipv4 address // case ISAKMP_ID_IPV4_ADDR: { // // is ids's address euqal to // idt's address // if( ids.addr1.s_addr != idt.addr1.s_addr ) return false; break; } // // ipv4 address to ipv4 network // case ISAKMP_ID_IPV4_ADDR_SUBNET: { // // convert to subnet addresses // unsigned long subnet1 = idt.addr1.s_addr & idt.addr2.s_addr; unsigned long subnet2 = ids.addr1.s_addr & idt.addr2.s_addr; // // is ids's subnet address equal // to idt's subnet address // if( subnet2 != subnet1 ) return false; break; } // // ipv4 address to ipv4 range // case ISAKMP_ID_IPV4_ADDR_RANGE: { // // is ids's address within idt's // address range // if( ( ids.addr1.s_addr < idt.addr1.s_addr ) && ( ids.addr1.s_addr > idt.addr2.s_addr ) ) return false; break; } } break; } case ISAKMP_ID_IPV4_ADDR_SUBNET: { switch( idt.type ) { // // ipv4 network to ipv4 address // case ISAKMP_ID_IPV4_ADDR: { // // is ids's address equal to // idt's subnet address with // idt's netmask being 32 bits // if( ( ids.addr1.s_addr != idt.addr1.s_addr ) || ( ids.addr2.s_addr != 0xffffffff ) ) return false; break; } // // ipv4 network to ipv4 network // case ISAKMP_ID_IPV4_ADDR_SUBNET: { // // is ids's subnet address and mask equal // if( ( ids.addr1.s_addr != idt.addr1.s_addr ) || ( ids.addr2.s_addr != idt.addr2.s_addr ) ) return false; break; } // // ipv4 network to ipv4 range // case ISAKMP_ID_IPV4_ADDR_RANGE: { return false; } } break; } case ISAKMP_ID_IPV4_ADDR_RANGE: { // // ipv4 range to ... // return false; } } return true; } ike-2.2.1+dfsg/source/iked/ike.policy.cpp000066400000000000000000000470321223036517100201770ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "iked.h" bool _IKED::policy_get_addrs( PFKI_SPINFO * spinfo, IKE_SADDR & src, IKE_SADDR & dst ) { memset( &src, 0, sizeof( src ) ); memset( &dst, 0, sizeof( dst ) ); bool tunnel = false; long xindex = 0; while( !tunnel && ( xindex < PFKI_MAX_XFORMS ) ) { if( !spinfo->xforms[ xindex ].proto ) break; switch( spinfo->xforms[ xindex ].mode ) { case IPSEC_MODE_ANY: case IPSEC_MODE_TRANSPORT: { src.saddr = spinfo->paddr_src.saddr; dst.saddr = spinfo->paddr_dst.saddr; break; } case IPSEC_MODE_TUNNEL: src.saddr = spinfo->xforms[ xindex ].saddr_src; dst.saddr = spinfo->xforms[ xindex ].saddr_dst; tunnel = true; break; } xindex++; } return true; } bool _IKED::policy_cmp_prots( PFKI_SPINFO * spinfo1, PFKI_SPINFO * spinfo2 ) { long xindex = 0; while( xindex < PFKI_MAX_XFORMS ) { // // compare the protocols // if( spinfo1->xforms[ xindex ].proto != spinfo2->xforms[ xindex ].proto ) return false; // // compare the mode // if( spinfo1->xforms[ xindex ].mode != spinfo2->xforms[ xindex ].mode ) return false; // // compare the level // if( spinfo1->xforms[ xindex ].level != spinfo2->xforms[ xindex ].level ) return false; xindex++; } return true; } bool _IKED::policy_list_create( IDB_TUNNEL * tunnel, bool initiator ) { // // if we are the responder, make // sure we generate an id list // before attempting to create // the policies // if( !initiator ) { log.txt( LLOG_INFO, "ii : creating policy id list\n" ); long index = 0; IDB_ENTRY_NETMAP * netmap; while( tunnel->peer->netmaps.get( &netmap, index++ ) ) { // // perform group checking if appropriate // if( netmap->group.size() ) { if( tunnel->peer->plcy_mode == POLICY_MODE_COMPAT ) { log.txt( LLOG_ERROR, "!! : - cannot validate netgroup %s before xauth\n", netmap->idlist->name.text() ); continue; } if( !tunnel->xauth.user.size() || !tunnel->xauth.pass.size() ) { log.txt( LLOG_ERROR, "!! : - cannot validate netgroup %s without xauth\n", netmap->idlist->name.text() ); continue; } if( !tunnel->peer->xauth_source->auth_grp( tunnel->xauth, netmap->group ) ) { log.txt( LLOG_INFO, "ii : - xauth user %s group %s membership rejected ( %s )\n", tunnel->xauth.user.text(), netmap->group.text(), tunnel->peer->xauth_source->name() ); continue; } log.txt( LLOG_INFO, "ii : - xauth user %s group %s membership accepted ( %s )\n", tunnel->xauth.user.text(), netmap->group.text(), tunnel->peer->xauth_source->name() ); } // // add netgroup ids to the tunnel list // log.txt( LLOG_INFO, "ii : - adding policy ids for netgroup %s\n", netmap->idlist->name.text() ); long index2 = 0; IKE_PH2ID ph2id; while( netmap->idlist->get( ph2id, index2++ ) ) { if( netmap->mode == UNITY_SPLIT_INCLUDE ) tunnel->idlist_incl.add( ph2id ); else tunnel->idlist_excl.add( ph2id ); } } } // // determine ipsec policy level value // u_int8_t ipsec_level = IPSEC_LEVEL_DEFAULT; switch( tunnel->peer->plcy_level ) { case POLICY_LEVEL_USE: ipsec_level = IPSEC_LEVEL_USE; break; case POLICY_LEVEL_SHARED: case POLICY_LEVEL_REQUIRE: ipsec_level = IPSEC_LEVEL_REQUIRE; break; case POLICY_LEVEL_UNIQUE: ipsec_level = IPSEC_LEVEL_UNIQUE; break; } log.txt( LLOG_DEBUG, "ii : generating IPSEC security policies at %s level\n", pfki.name( NAME_SPLEVEL, ipsec_level ) ); // // if we have a empty remote toplology // list, add a single all-networks id // and flag the tunnel as force all // IKE_PH2ID id1; IKE_PH2ID id2; if( !tunnel->idlist_incl.count() ) { memset( &id2, 0, sizeof( id2 ) ); id2.type = ISAKMP_ID_IPV4_ADDR_SUBNET; tunnel->idlist_incl.add( id2 ); tunnel->force_all = true; } // // add NONE policies to ensure we will // still communicate with our peer for // the case where IPSEC policies exist // that encrypt traffic between client // and gateway endpoint addresses // memset( &id1, 0, sizeof( id1 ) ); id1.type = ISAKMP_ID_IPV4_ADDR; id1.addr1 = tunnel->saddr_l.saddr4.sin_addr; memset( &id2, 0, sizeof( id2 ) ); id2.type = ISAKMP_ID_IPV4_ADDR; id2.addr1 = tunnel->saddr_r.saddr4.sin_addr; policy_create( tunnel, IPSEC_POLICY_NONE, IPSEC_LEVEL_DEFAULT, id1, id2, true ); #ifdef WIN32 IPROUTE_ENTRY entry; memset( &entry, 0, sizeof( entry ) ); entry.addr = tunnel->saddr_r.saddr4.sin_addr; if( iproute.best( entry ) && !entry.local ) { memset( &id1, 0, sizeof( id1 ) ); id1.type = ISAKMP_ID_IPV4_ADDR; id1.addr1 = tunnel->xconf.addr; memset( &id2, 0, sizeof( id2 ) ); id2.type = ISAKMP_ID_IPV4_ADDR; id2.addr1 = entry.next; policy_create( tunnel, IPSEC_POLICY_NONE, IPSEC_LEVEL_DEFAULT, id1, id2, false ); } #endif // // build the client id // memset( &id1, 0, sizeof( id1 ) ); id1.type = ISAKMP_ID_IPV4_ADDR; id1.addr1.s_addr = tunnel->xconf.addr.s_addr; id1.addr2.s_addr = 0; // // create a discard or none policy // pair for each id in our exclude list // long index = 0; while( tunnel->idlist_excl.get( id2, index++ ) ) { if( initiator ) policy_create( tunnel, IPSEC_POLICY_NONE, IPSEC_LEVEL_DEFAULT, id1, id2, true ); else policy_create( tunnel, IPSEC_POLICY_DISCARD, IPSEC_LEVEL_DEFAULT, id2, id1, true ); } // // create an ipsec policy pair for // each id in our include list // index = 0; while( tunnel->idlist_incl.get( id2, index++ ) ) { if( initiator ) policy_create( tunnel, IPSEC_POLICY_IPSEC, ipsec_level, id1, id2, true ); else policy_create( tunnel, IPSEC_POLICY_IPSEC, ipsec_level, id2, id1, true ); } return true; } bool _IKED::policy_list_remove( IDB_TUNNEL * tunnel, bool initiator ) { // // determine ipsec policy level value // u_int8_t ipsec_level = IPSEC_LEVEL_DEFAULT; switch( tunnel->peer->plcy_level ) { case POLICY_LEVEL_USE: ipsec_level = IPSEC_LEVEL_USE; break; case POLICY_LEVEL_SHARED: case POLICY_LEVEL_REQUIRE: ipsec_level = IPSEC_LEVEL_REQUIRE; break; case POLICY_LEVEL_UNIQUE: ipsec_level = IPSEC_LEVEL_UNIQUE; break; } // // build the client id // IKE_PH2ID id1; memset( &id1, 0, sizeof( id1 ) ); id1.type = ISAKMP_ID_IPV4_ADDR; id1.addr1.s_addr = tunnel->xconf.addr.s_addr; id1.addr2.s_addr = 0; // // remove the ipsec policy pair for // each id in our include list // IKE_PH2ID id2; long index = 0; while( tunnel->idlist_incl.get( id2, index++ ) ) { if( initiator ) policy_remove( tunnel, IPSEC_POLICY_IPSEC, ipsec_level, id1, id2, true ); else policy_remove( tunnel, IPSEC_POLICY_IPSEC, ipsec_level, id2, id1, true ); } // // remove the discard or none policy // pair for each id in our exclude list // index = 0; while( tunnel->idlist_excl.get( id2, index++ ) ) { if( initiator ) policy_remove( tunnel, IPSEC_POLICY_NONE, IPSEC_LEVEL_DEFAULT, id1, id2, true ); else policy_remove( tunnel, IPSEC_POLICY_DISCARD, IPSEC_LEVEL_DEFAULT, id2, id1, true ); } // // remove our gateway NONE policies // #ifdef WIN32 IPROUTE_ENTRY entry; memset( &entry, 0, sizeof( entry ) ); entry.addr = tunnel->saddr_r.saddr4.sin_addr; if( iproute.best( entry ) && !entry.local ) { memset( &id1, 0, sizeof( id1 ) ); id1.type = ISAKMP_ID_IPV4_ADDR; id1.addr1 = tunnel->xconf.addr; memset( &id2, 0, sizeof( id2 ) ); id2.type = ISAKMP_ID_IPV4_ADDR; id2.addr1 = entry.next; policy_remove( tunnel, IPSEC_POLICY_NONE, IPSEC_LEVEL_DEFAULT, id1, id2, false ); } #endif memset( &id1, 0, sizeof( id1 ) ); id1.type = ISAKMP_ID_IPV4_ADDR; id1.addr1 = tunnel->saddr_l.saddr4.sin_addr; memset( &id2, 0, sizeof( id2 ) ); id2.type = ISAKMP_ID_IPV4_ADDR; id2.addr1 = tunnel->saddr_r.saddr4.sin_addr; policy_remove( tunnel, IPSEC_POLICY_NONE, IPSEC_LEVEL_DEFAULT, id1, id2, true ); if( tunnel->force_all ) tunnel->force_all = false; return true; } bool _IKED::policy_dhcp_create( IDB_TUNNEL * tunnel ) { // // determine ipsec policy level value // u_int8_t ipsec_level = IPSEC_LEVEL_DEFAULT; switch( tunnel->peer->plcy_level ) { case POLICY_LEVEL_USE: ipsec_level = IPSEC_LEVEL_USE; break; case POLICY_LEVEL_SHARED: case POLICY_LEVEL_REQUIRE: ipsec_level = IPSEC_LEVEL_REQUIRE; break; case POLICY_LEVEL_UNIQUE: ipsec_level = IPSEC_LEVEL_UNIQUE; break; } // // create our DHCP over IPsec policies // log.txt( LLOG_DEBUG, "ii : creating IPsec over DHCP policies\n" ); IKE_PH2ID src; memset( &src, 0, sizeof( src ) ); src.type = ISAKMP_ID_IPV4_ADDR; src.prot = PROTO_IP_UDP; src.port = htons( UDP_PORT_DHCPS ); src.addr1 = tunnel->saddr_l.saddr4.sin_addr; IKE_PH2ID dst; memset( &dst, 0, sizeof( dst ) ); dst.type = ISAKMP_ID_IPV4_ADDR; dst.prot = PROTO_IP_UDP; dst.port = htons( UDP_PORT_DHCPS ); dst.addr1 = tunnel->saddr_r.saddr4.sin_addr; return policy_create( tunnel, IPSEC_POLICY_IPSEC, ipsec_level, src, dst, false ); } bool _IKED::policy_dhcp_remove( IDB_TUNNEL * tunnel ) { // // determine ipsec policy level value // u_int8_t ipsec_level = IPSEC_LEVEL_DEFAULT; switch( tunnel->peer->plcy_level ) { case POLICY_LEVEL_USE: ipsec_level = IPSEC_LEVEL_USE; break; case POLICY_LEVEL_SHARED: case POLICY_LEVEL_REQUIRE: ipsec_level = IPSEC_LEVEL_REQUIRE; break; case POLICY_LEVEL_UNIQUE: ipsec_level = IPSEC_LEVEL_UNIQUE; break; } // // remove our DHCP over IPsec policies // log.txt( LLOG_DEBUG, "ii : removing IPsec over DHCP policies\n" ); IKE_PH2ID src; memset( &src, 0, sizeof( src ) ); src.type = ISAKMP_ID_IPV4_ADDR; src.prot = PROTO_IP_UDP; src.port = htons( UDP_PORT_DHCPS ); src.addr1 = tunnel->saddr_l.saddr4.sin_addr; IKE_PH2ID dst; memset( &dst, 0, sizeof( dst ) ); dst.type = ISAKMP_ID_IPV4_ADDR; dst.prot = PROTO_IP_UDP; dst.port = htons( UDP_PORT_DHCPS ); dst.addr1 = tunnel->saddr_r.saddr4.sin_addr; return policy_remove( tunnel, IPSEC_POLICY_IPSEC, ipsec_level, src, dst, false ); } bool _IKED::policy_create( IDB_TUNNEL * tunnel, u_int16_t type, u_int8_t level, IKE_PH2ID & id1, IKE_PH2ID & id2, bool route ) { char txtid_src[ LIBIKE_MAX_TEXTP2ID ]; char txtid_dst[ LIBIKE_MAX_TEXTP2ID ]; // // define inbound policy // PFKI_SPINFO spinfo; memset( &spinfo, 0, sizeof( spinfo ) ); spinfo.sp.type = type; spinfo.sp.dir = IPSEC_DIR_INBOUND; ph2id_paddr( id2, spinfo.paddr_src ); ph2id_paddr( id1, spinfo.paddr_dst ); if( type == IPSEC_POLICY_IPSEC ) { spinfo.xforms[ 0 ].proto = PROTO_IP_ESP; spinfo.xforms[ 0 ].mode = IPSEC_MODE_TUNNEL; spinfo.xforms[ 0 ].level = level; if( level == IPSEC_LEVEL_UNIQUE ) spinfo.xforms[ 0 ].reqid = policyid++; cpy_sockaddr( tunnel->saddr_r.saddr, spinfo.xforms[ 0 ].saddr_src, false ); cpy_sockaddr( tunnel->saddr_l.saddr, spinfo.xforms[ 0 ].saddr_dst, false ); } text_ph2id( txtid_src, &id2 ); text_ph2id( txtid_dst, &id1 ); log.txt( LLOG_INFO, "ii : creating %s %s policy %s -> %s\n", pfki.name( NAME_SPTYPE, spinfo.sp.type ), pfki.name( NAME_SPDIR, spinfo.sp.dir ), txtid_src, txtid_dst ); // // create an inbound policy object // IDB_POLICY * policy = new IDB_POLICY( &spinfo ); if( policy == NULL ) { log.txt( LLOG_ERROR, "!! : failed to allocate inbound policy object\n" ); return false; } // // add the inbbound policy to spd // policy->add( true ); policy->dec( true ); pfkey_send_spadd( &spinfo ); // // define outbound policy // memset( &spinfo, 0, sizeof( spinfo ) ); spinfo.sp.type = type; spinfo.sp.dir = IPSEC_DIR_OUTBOUND; ph2id_paddr( id1, spinfo.paddr_src ); ph2id_paddr( id2, spinfo.paddr_dst ); if( type == IPSEC_POLICY_IPSEC ) { spinfo.xforms[ 0 ].proto = PROTO_IP_ESP; spinfo.xforms[ 0 ].mode = IPSEC_MODE_TUNNEL; spinfo.xforms[ 0 ].level = level; if( level == IPSEC_LEVEL_UNIQUE ) spinfo.xforms[ 0 ].reqid = policyid++; cpy_sockaddr( tunnel->saddr_l.saddr, spinfo.xforms[ 0 ].saddr_src, false ); cpy_sockaddr( tunnel->saddr_r.saddr, spinfo.xforms[ 0 ].saddr_dst, false ); } text_ph2id( txtid_src, &id1 ); text_ph2id( txtid_dst, &id2 ); log.txt( LLOG_INFO, "ii : creating %s %s policy %s -> %s\n", pfki.name( NAME_SPTYPE, spinfo.sp.type ), pfki.name( NAME_SPDIR, spinfo.sp.dir ), txtid_src, txtid_dst ); text_addr( txtid_dst, &spinfo.paddr_dst, false, true ); // // create an outbound policy object // policy = new IDB_POLICY( &spinfo ); if( policy == NULL ) { log.txt( LLOG_ERROR, "!! : failed to allocate outbound policy object\n" ); return false; } // // set special flags for outbound policies // if( tunnel->peer->nailed ) policy->flags |= PFLAG_NAILED; if( ( type == IPSEC_POLICY_IPSEC ) && ( tunnel->tstate & TSTATE_POLICY_INIT ) ) { policy->flags |= PFLAG_INITIAL; tunnel->tstate &= ~TSTATE_POLICY_INIT; } // // create client policy route // if( route && ( tunnel->peer->contact == IPSEC_CONTACT_CLIENT ) ) { IPROUTE_ENTRY & route_entry = policy->route_entry; switch( type ) { case IPSEC_POLICY_IPSEC: { route_entry.local = true; route_entry.iface = tunnel->xconf.addr; route_entry.addr = id2.addr1; route_entry.mask = id2.addr2; route_entry.next = tunnel->xconf.addr; if( id2.type == ISAKMP_ID_IPV4_ADDR ) route_entry.mask.s_addr = 0xffffffff; iproute.increment( route_entry.addr, route_entry.mask ); if( iproute.add( route_entry ) ) policy->flags |= PFLAG_ROUTED; break; } case IPSEC_POLICY_NONE: { route_entry.addr = id2.addr1; if( iproute.best( route_entry ) ) { route_entry.addr = id2.addr1; route_entry.mask = id2.addr2; if( id2.type == ISAKMP_ID_IPV4_ADDR ) route_entry.mask.s_addr = 0xffffffff; if( iproute.add( route_entry ) ) policy->flags |= PFLAG_ROUTED; } break; } } if( policy->flags & PFLAG_ROUTED ) { log.txt( LLOG_INFO, "ii : created %s policy route for %s\n", pfki.name( NAME_SPTYPE, type ), txtid_dst ); } else { log.txt( LLOG_ERROR, "!! : failed to create %s policy route for %s\n", pfki.name( NAME_SPTYPE, type ), txtid_dst ); } } // // add the outbound policy to spd // policy->add( true ); policy->dec( true ); pfkey_send_spadd( &spinfo ); return true; } bool _IKED::policy_remove( IDB_TUNNEL * tunnel, u_int16_t type, u_int8_t level, IKE_PH2ID & id1, IKE_PH2ID & id2, bool route ) { char txtid_src[ LIBIKE_MAX_TEXTP2ID ]; char txtid_dst[ LIBIKE_MAX_TEXTP2ID ]; IDB_POLICY * policy; bool route_deleted = false; long flags = 0; IPROUTE_ENTRY route_entry; IKE_SADDR * src; IKE_SADDR * dst; // // remove inbound policy // src = NULL; dst = NULL; if( type == IPSEC_POLICY_IPSEC ) { src = &tunnel->saddr_r; dst = &tunnel->saddr_l; } if( idb_list_policy.find( false, &policy, IPSEC_DIR_INBOUND, type, NULL, NULL, src, dst, &id2, &id1 ) ) { text_ph2id( txtid_src, &id2 ); text_ph2id( txtid_dst, &id1 ); log.txt( LLOG_INFO, "ii : removing %s %s policy %s -> %s\n", pfki.name( NAME_SPTYPE, policy->sp.type ), pfki.name( NAME_SPDIR, policy->sp.dir ), txtid_src, txtid_dst ); pfkey_send_spdel( policy ); policy->dec( false ); } // // remove outbound policy // src = NULL; dst = NULL; if( type == IPSEC_POLICY_IPSEC ) { src = &tunnel->saddr_l; dst = &tunnel->saddr_r; } if( idb_list_policy.find( false, &policy, IPSEC_DIR_OUTBOUND, type, NULL, NULL, src, dst, &id1, &id2 ) ) { route_entry = policy->route_entry; flags = policy->flags; text_ph2id( txtid_src, &id1 ); text_ph2id( txtid_dst, &id2 ); log.txt( LLOG_INFO, "ii : removing %s %s policy %s -> %s\n", pfki.name( NAME_SPTYPE, policy->sp.type ), pfki.name( NAME_SPDIR, policy->sp.dir ), txtid_src, txtid_dst ); text_addr( txtid_dst, &policy->paddr_dst, false, true ); pfkey_send_spdel( policy ); policy->dec( false ); } // // remove client policy route // if( route && ( flags & PFLAG_ROUTED ) && ( tunnel->peer->contact == IPSEC_CONTACT_CLIENT ) ) { switch( type ) { case IPSEC_POLICY_IPSEC: { route_deleted = iproute.del( route_entry ); iproute.decrement( route_entry.addr, route_entry.mask ); break; } case IPSEC_POLICY_NONE: { route_deleted = iproute.del( route_entry ); break; } } if( route_deleted ) { text_ph2id( txtid_dst, &id2 ); log.txt( LLOG_INFO, "ii : removed %s policy route for %s\n", pfki.name( NAME_SPTYPE, type ), txtid_dst ); } else { text_ph2id( txtid_dst, &id2 ); log.txt( LLOG_ERROR, "!! : failed to remove %s policy route for %s\n", pfki.name( NAME_SPTYPE, type ), txtid_dst ); } } return true; } ike-2.2.1+dfsg/source/iked/ike.proposal.cpp000066400000000000000000000763621223036517100205470ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "iked.h" long _IKED::phase1_gen_prop( IDB_PH1 * ph1 ) { // // phase1 proposals are described internally // as a list of proposal structures. since // isakmp only uses one proposal per sa, the // ony values that vary are transform values // unsigned char tnumb = 0; // cipher algorithms unsigned short clist[] = { IKE_CIPHER_AES, IKE_CIPHER_BLOWFISH, IKE_CIPHER_3DES, IKE_CIPHER_CAST, IKE_CIPHER_DES }; // hash algorithms unsigned short hlist[] = { IKE_HASH_MD5, IKE_HASH_SHA1 }; // dh groups unsigned short glist[] = { IKE_GRP_GROUP14, IKE_GRP_GROUP5, IKE_GRP_GROUP2, IKE_GRP_GROUP1 }; // // acquire our peer isakmp proposal // IKE_PROPOSAL * peerprop; if( !ph1->tunnel->peer->proposals.get( &peerprop, 0, ISAKMP_PROTO_ISAKMP ) ) return LIBIKE_FAILED; // // step through the cipher list // long ccount = sizeof( clist ) / sizeof( unsigned short ); long cindex = 0; // // restrict to specified cipher // if( peerprop->ciph_id ) { clist[ 0 ] = peerprop->ciph_id; ccount = 1; } for( ; cindex < ccount; cindex++ ) { // // determine valid key sizes // short klen = 0; short kmin = 0; short step = 1; switch( clist[ cindex ] ) { case IKE_CIPHER_AES: case IKE_CIPHER_BLOWFISH: klen = 256; kmin = 128; step = 64; break; } // // restrict to specified key size // if( peerprop->ciph_kl ) { klen = peerprop->ciph_kl; kmin = klen; } // // step through key sizes // for( ; klen >= kmin; klen -= step ) { // // step through the hash list // long hcount = sizeof( hlist ) / sizeof( unsigned short ); long hindex = 0; // // restrict to specified hash // if( peerprop->hash_id ) { hlist[ 0 ] = peerprop->hash_id; hcount = 1; } for( ; hindex < hcount; hindex++ ) { // // step through the dh group list // long gcount = sizeof( glist ) / sizeof( unsigned short ); long gindex = 0; // // restrict to specified hash // if( peerprop->dhgr_id ) { glist[ 0 ] = peerprop->dhgr_id; gcount = 1; } for( ; gindex < gcount; gindex++ ) { // // build proposal transform // IKE_PROPOSAL proposal; memset( &proposal, 0, sizeof( proposal ) ); proposal.pnumb = 1; proposal.tnumb = ++tnumb; proposal.proto = ISAKMP_PROTO_ISAKMP; proposal.xform = IKE_ATTR_TRANSFORM; proposal.ciph_id = clist[ cindex ]; proposal.ciph_kl = klen; proposal.hash_id = hlist[ hindex ]; proposal.dhgr_id = glist[ gindex ]; proposal.auth_id = peerprop->auth_id; proposal.life_sec = peerprop->life_sec; proposal.life_kbs = peerprop->life_kbs; // // add proposal transform // ph1->plist_l.add( &proposal, ( tnumb == 1 ) ); } } } } return LIBIKE_OK; } long _IKED::phase1_sel_prop( IDB_PH1 * ph1 ) { // // attempt to match a phase1 proposal that // was sumitted by the remote peer // // // step through our local proposal list // IKE_PROPOSAL * lproposal; long lpindex = 0; long ltcount; long ltindex; while( ph1->plist_l.nextp( &lproposal, lpindex, ltindex, ltcount ) ) { // // step through our remote proposal list // IKE_PROPOSAL * rproposal; long rpindex = 0; long rtcount; long rtindex; while( ph1->plist_r.nextp( &rproposal, rpindex, rtindex, rtcount ) ) { // // step through the local tranform list // while( ph1->plist_l.nextt( &lproposal, ltindex ) ) { // // step through the remote transform list // long ttindex = rtindex; while( ph1->plist_r.nextt( &rproposal, ttindex ) ) { // // match all other information // if( !phase1_cmp_prop( rproposal, lproposal, ph1->initiator, ph1->tunnel->peer->life_check ) ) continue; // // we found a match // IKE_PROPOSAL ltemp; IKE_PROPOSAL rtemp; memcpy( <emp, lproposal, sizeof( ltemp ) ); memcpy( &rtemp, rproposal, sizeof( rtemp ) ); ph1->plist_l.clean(); ph1->plist_r.clean(); // // check and potentialy modify lifetime // values if we are the responder // if( !ph1->initiator ) { switch( ph1->tunnel->peer->life_check ) { case LTIME_OBEY: { // // always use the initiators // if( ltemp.life_sec != rtemp.life_sec ) { log.txt( LLOG_INFO, "ii : adjusting %s lifetime %i -> %i ( obey )\n", find_name( NAME_PROTOCOL, ltemp.proto ), ltemp.life_sec, rtemp.life_sec ); ltemp.life_sec = rtemp.life_sec; } } case LTIME_CLAIM: { // // use initiators when shorter // if( ltemp.life_sec > rtemp.life_sec ) { log.txt( LLOG_INFO, "ii : adjusting %s lifetime %i -> %i ( claim )\n", find_name( NAME_PROTOCOL, ltemp.proto ), ltemp.life_sec, rtemp.life_sec ); ltemp.life_sec = rtemp.life_sec; } // // use responders when shorter and log // if( ltemp.life_sec < rtemp.life_sec ) { log.txt( LLOG_INFO, "ii : using responder %s lifetime %i seconds, initiators is longer ( claim )\n", find_name( NAME_PROTOCOL, ltemp.proto ), ltemp.life_sec ); } } case LTIME_STRICT: { // // use initiators when shorter // if( ltemp.life_sec > rtemp.life_sec ) { log.txt( LLOG_INFO, "ii : adjusting %s lifetime %i -> %i ( strict )\n", find_name( NAME_PROTOCOL, ltemp.proto ), ltemp.life_sec, rtemp.life_sec ); ltemp.life_sec = rtemp.life_sec; } } } } // // set protocol and transform number // ltemp.pnumb = rtemp.pnumb; ltemp.tnumb = rtemp.tnumb; // // we found a proposal and transform // match, add them to our lists // ph1->plist_l.add( <emp, true ); ph1->plist_r.add( &rtemp, true ); return LIBIKE_OK; } } } } return LIBIKE_FAILED; } bool _IKED::phase1_cmp_prop( IKE_PROPOSAL * proposal1, IKE_PROPOSAL * proposal2, bool initiator, long life_check ) { // // check proposal protocol // if( proposal1->proto != proposal2->proto ) { log.txt( LLOG_DEBUG, "ii : unmatched phase1 proposal/transform\n" "ii : protocol ( %s != %s )\n", find_name( NAME_PROTOCOL, proposal1->proto ), find_name( NAME_PROTOCOL, proposal2->proto ) ); return false; } // // validate phase1 protocol // long xtype = 0; long htype = NAME_MAUTH; switch( proposal2->proto ) { case ISAKMP_PROTO_ISAKMP: xtype = NAME_XFORM_ISAKMP; break; default: { log.txt( LLOG_DEBUG, "ii : internal error, phase1 protocol unknown %i\n", proposal2->proto ); return false; } } // // check proposal transform type // if( proposal1->xform != proposal2->xform ) { log.txt( LLOG_DEBUG, "ii : unmatched %s proposal/transform\n" "ii : crypto transform type ( %s != %s )\n", find_name( NAME_PROTOCOL, proposal1->proto ), find_name( xtype, proposal1->xform ), find_name( xtype, proposal2->xform ) ); return false; } // // check cipher selection // if( proposal1->ciph_id != proposal2->ciph_id ) { log.txt( LLOG_DEBUG, "ii : unmatched %s proposal/transform\n" "ii : cipher type ( %s != %s )\n", find_name( NAME_PROTOCOL, proposal1->proto ), find_name( NAME_CIPHER, proposal1->ciph_id ), find_name( NAME_CIPHER, proposal2->ciph_id ) ); return false; } // // check cipher key legth // if( proposal1->ciph_kl != proposal2->ciph_kl ) { log.txt( LLOG_DEBUG, "ii : unmatched %s proposal/transform\n" "ii : key length ( %i != %i )\n", find_name( NAME_PROTOCOL, proposal1->proto ), proposal1->ciph_kl, proposal2->ciph_kl ); return false; } // // check hash selection // if( proposal1->hash_id != proposal2->hash_id ) { log.txt( LLOG_DEBUG, "ii : unmatched %s proposal/transform\n" "ii : hash type ( %s != %s )\n", find_name( NAME_PROTOCOL, proposal1->proto ), find_name( htype, proposal1->hash_id ), find_name( htype, proposal2->hash_id ) ); return false; } // // check dh group description // if( proposal1->dhgr_id != proposal2->dhgr_id ) { log.txt( LLOG_DEBUG, "ii : unmatched %s proposal/transform\n" "ii : dh group description ( %s != %s )\n", find_name( NAME_PROTOCOL, proposal1->proto ), find_name( NAME_GROUP, proposal1->dhgr_id ), find_name( NAME_GROUP, proposal2->dhgr_id ) ); return false; } // // check authentication method // if( proposal1->auth_id != proposal2->auth_id ) { log.txt( LLOG_DEBUG, "ii : unmatched %s proposal/transform\n" "ii : hmac type ( %s != %s )\n", find_name( NAME_PROTOCOL, proposal1->proto ), find_name( NAME_PAUTH, proposal1->auth_id ), find_name( NAME_PAUTH, proposal2->auth_id ) ); return false; } // // check lifetime values // if( !initiator ) { switch( life_check ) { case LTIME_OBEY: case LTIME_CLAIM: break; case LTIME_STRICT: { if( proposal1->life_sec < proposal2->life_sec ) { log.txt( LLOG_DEBUG, "ii : unmatched %s proposal/transform\n" "ii : lifetime seconds ( %i < %i strict )\n", find_name( NAME_PROTOCOL, proposal1->proto ), proposal1->life_sec, proposal2->life_sec ); return false; } break; } case LTIME_EXACT: { if( proposal1->life_sec != proposal2->life_sec ) { log.txt( LLOG_DEBUG, "ii : unmatched %s proposal/transform\n" "ii : lifetime seconds ( %i != %i exact )\n", find_name( NAME_PROTOCOL, proposal1->proto ), proposal1->life_sec, proposal2->life_sec ); return false; } break; } } } // // check peer for RFC compliance // if( initiator ) if( proposal1->tnumb != proposal2->tnumb ) log.txt( LLOG_ERROR, "!! : peer violates RFC, transform number mismatch ( %i != %i )\n", proposal1->tnumb, proposal2->tnumb ); // // proposal and transform matched // char klentxt[ 32 ]; if( proposal1->ciph_kl ) sprintf_s( klentxt, 32, "%i bits", proposal1->ciph_kl ); else sprintf_s( klentxt, 32, "default" ); log.txt( LLOG_INFO, "ii : matched %s proposal #%i transform #%i\n" "ii : - transform = %s\n" "ii : - cipher type = %s\n" "ii : - key length = %s\n" "ii : - hash type = %s\n" "ii : - dh group = %s\n" "ii : - auth type = %s\n" "ii : - life seconds = %i\n" "ii : - life kbytes = %i\n", find_name( NAME_PROTOCOL, proposal1->proto ), proposal1->pnumb, proposal1->tnumb, find_name( xtype, proposal1->xform ), find_name( NAME_CIPHER, proposal1->ciph_id ), klentxt, find_name( NAME_HASH, proposal1->hash_id ), find_name( NAME_GROUP, proposal1->dhgr_id ), find_name( NAME_PAUTH, proposal1->auth_id ), proposal1->life_sec, proposal1->life_kbs ); return true; } long _IKED::phase2_gen_prop( IDB_PH2 * ph2, IDB_POLICY * policy ) { // // phase2 proposals are described internally // as a list of proposal structures. we use // the caller supplied policy to generate a // list of complimentary proposal bundles // long xindex = PFKI_MAX_XFORMS - 1; while( xindex >= 0 ) { // // determine the protection suite // unsigned char tnumb = 0; switch( policy->xforms[ xindex ].proto ) { // // AH // case PROTO_IP_AH: { // transform types unsigned char tlist[] = { ISAKMP_AH_MD5, ISAKMP_AH_SHA, ISAKMP_AH_SHA256, ISAKMP_AH_SHA384, ISAKMP_AH_SHA512, }; // // acquire our peer ah proposal // IKE_PROPOSAL * peerprop; if( !ph2->tunnel->peer->proposals.get( &peerprop, 0, ISAKMP_PROTO_IPSEC_AH ) ) break; // // step through the transform list // long tcount = sizeof( tlist ) / sizeof( unsigned char ); long tindex = 0; // // restrict to specified transform // if( peerprop->xform ) { tlist[ 0 ] = peerprop->xform; tcount = 1; } for( ; tindex < tcount; tindex++ ) { // // build proposal transform // IKE_PROPOSAL proposal; memset( &proposal, 0, sizeof( proposal ) ); proposal.pnumb = 1; proposal.tnumb = ++tnumb; proposal.proto = peerprop->proto; if( policy->xforms[ xindex ].mode == IPSEC_MODE_TUNNEL ) proposal.encap = ISAKMP_ENCAP_TUNNEL; else proposal.encap = ISAKMP_ENCAP_TRANSPORT; proposal.xform = tlist[ tindex ]; switch( proposal.xform ) { case ISAKMP_AH_MD5: proposal.hash_id = ISAKMP_AUTH_HMAC_MD5; break; case ISAKMP_AH_SHA: proposal.hash_id = ISAKMP_AUTH_HMAC_SHA1; break; case ISAKMP_AH_SHA256: proposal.hash_id = ISAKMP_AUTH_HMAC_SHA2_256; break; case ISAKMP_AH_SHA384: proposal.hash_id = ISAKMP_AUTH_HMAC_SHA2_384; break; case ISAKMP_AH_SHA512: proposal.hash_id = ISAKMP_AUTH_HMAC_SHA2_512; break; } proposal.life_sec = peerprop->life_sec; proposal.life_kbs = peerprop->life_kbs; // // add proposal transform // ph2->plist_l.add( &proposal, ( tnumb == 1 ) ); } break; } // // ESP // case PROTO_IP_ESP: { // transform types unsigned char tlist[] = { ISAKMP_ESP_AES, ISAKMP_ESP_BLOWFISH, ISAKMP_ESP_3DES, ISAKMP_ESP_CAST, ISAKMP_ESP_DES }; // authentication algorithms unsigned short alist[] = { ISAKMP_AUTH_HMAC_MD5, ISAKMP_AUTH_HMAC_SHA1, ISAKMP_AUTH_HMAC_SHA2_256, ISAKMP_AUTH_HMAC_SHA2_384, ISAKMP_AUTH_HMAC_SHA2_512 }; // // acquire our peer esp proposal // IKE_PROPOSAL * peerprop; if( !ph2->tunnel->peer->proposals.get( &peerprop, 0, ISAKMP_PROTO_IPSEC_ESP ) ) break; // // step through the transform list // long tcount = sizeof( tlist ) / sizeof( unsigned char ); long tindex = 0; // // restrict to specified transform // if( peerprop->xform ) { tlist[ 0 ] = peerprop->xform; tcount = 1; } for( ; tindex < tcount; tindex++ ) { // // determine valid key sizes // short klen = 0; short kmin = 0; short step = 1; switch( tlist[ tindex ] ) { case ISAKMP_ESP_AES: case ISAKMP_ESP_BLOWFISH: klen = 256; kmin = 128; step = 64; break; } // // restrict to specified key size // if( peerprop->ciph_kl ) { klen = peerprop->ciph_kl; kmin = klen; } // // step through key sizes // for( ; klen >= kmin; klen -= step ) { // // step through the auth list // long acount = sizeof( alist ) / sizeof( unsigned short ); long aindex = 0; // // restrict to specified msg auth // if( peerprop->hash_id ) { alist[ 0 ] = peerprop->hash_id; acount = 1; } for( ; aindex < acount; aindex++ ) { // // build proposal transform // IKE_PROPOSAL proposal; memset( &proposal, 0, sizeof( proposal ) ); proposal.pnumb = 1; proposal.tnumb = ++tnumb; proposal.proto = peerprop->proto; proposal.xform = tlist[ tindex ]; // // if natt was negotiated we need to // fix-up the encapsulation mode for // esp negotiations // if( policy->xforms[ xindex ].mode == IPSEC_MODE_TUNNEL ) { switch( ph2->tunnel->natt_version ) { case IPSEC_NATT_NONE: case IPSEC_NATT_CISCO: proposal.encap = ISAKMP_ENCAP_TUNNEL; break; case IPSEC_NATT_V00: case IPSEC_NATT_V01: case IPSEC_NATT_V02: case IPSEC_NATT_V03: proposal.encap = ISAKMP_ENCAP_VXX_UDP_TUNNEL; break; case IPSEC_NATT_RFC: proposal.encap = ISAKMP_ENCAP_RFC_UDP_TUNNEL; break; } } else { switch( ph2->tunnel->natt_version ) { case IPSEC_NATT_NONE: case IPSEC_NATT_CISCO: proposal.encap = ISAKMP_ENCAP_TRANSPORT; break; case IPSEC_NATT_V00: case IPSEC_NATT_V01: case IPSEC_NATT_V02: case IPSEC_NATT_V03: proposal.encap = ISAKMP_ENCAP_VXX_UDP_TRANSPORT; break; case IPSEC_NATT_RFC: proposal.encap = ISAKMP_ENCAP_RFC_UDP_TRANSPORT; break; } } proposal.ciph_kl = klen; proposal.hash_id = alist[ aindex ]; // // the config pfs group overrides // the proposal setting // if( ph2->tunnel->xconf.dhgr ) proposal.dhgr_id = ph2->tunnel->xconf.dhgr; else proposal.dhgr_id = peerprop->dhgr_id; if( proposal.dhgr_id ) ph2->dhgr_id = proposal.dhgr_id; // // set proposal lifetime values // proposal.life_sec = peerprop->life_sec; proposal.life_kbs = peerprop->life_kbs; // // add proposal transform // ph2->plist_l.add( &proposal, ( tnumb == 1 ) ); } } } break; } // // IPCOMP // case PROTO_IP_IPCOMP: { // transform types unsigned char tlist[] = { ISAKMP_IPCOMP_DEFLATE, ISAKMP_IPCOMP_LZS }; // // acquire our peer ipcomp proposal // IKE_PROPOSAL * peerprop; if( !ph2->tunnel->peer->proposals.get( &peerprop, 0, ISAKMP_PROTO_IPCOMP ) ) break; // // step through the transform list // long tcount = sizeof( tlist ) / sizeof( unsigned char ); long tindex = 0; // // restrict to specified transform // if( peerprop->xform ) { tlist[ 0 ] = peerprop->xform; tcount = 1; } for( ; tindex < tcount; tindex++ ) { // // build proposal transform // IKE_PROPOSAL proposal; memset( &proposal, 0, sizeof( proposal ) ); proposal.pnumb = 1; proposal.tnumb = ++tnumb; proposal.proto = peerprop->proto; if( policy->xforms[ xindex ].mode == IPSEC_MODE_TUNNEL ) proposal.encap = ISAKMP_ENCAP_TUNNEL; else proposal.encap = ISAKMP_ENCAP_TRANSPORT; proposal.xform = tlist[ tindex ]; proposal.life_sec = peerprop->life_sec; proposal.life_kbs = peerprop->life_kbs; // // add proposal transform // ph2->plist_l.add( &proposal, ( tnumb == 1 ) ); } break; } } xindex--; } return LIBIKE_OK; } long _IKED::phase2_sel_prop( IDB_PH2 * ph2 ) { // // attempt to match a phase2 proposal // bundle to a local proposal bundle // IDB_LIST_PROPOSAL plist_l; IDB_LIST_PROPOSAL plist_r; // // step through our local bundles // long lbindex = 0; long lpindex; long lpcount; while( ph2->plist_l.nextb( lbindex, lpindex, lpcount ) ) { // // step through our remote bundles // plist_l.clean(); long rbindex = 0; long rpindex; long rpcount; while( ph2->plist_r.nextb( rbindex, rpindex, rpcount ) ) { // // check that the local and remote // bundles have the same proposal // count // plist_r.clean(); if( rpcount != lpcount ) continue; // // step through our local proposals // IKE_PROPOSAL * lproposal; long ltcount; long ltindex; while( ph2->plist_l.nextp( &lproposal, lpindex, ltindex, ltcount ) ) { // // step through our remote proposals // IKE_PROPOSAL * rproposal; long rtcount; long rtindex; bool ptmatch = false; while( !ptmatch && ph2->plist_r.nextp( &rproposal, rpindex, rtindex, rtcount ) ) { // // step through the local tranforms // while( !ptmatch && ph2->plist_l.nextt( &lproposal, ltindex ) ) { // // step through the remote transforms // long ttindex = rtindex; while( !ptmatch && ph2->plist_r.nextt( &rproposal, ttindex ) ) { // // match the proposal / transform info // if( !phase2_cmp_prop( rproposal, lproposal, ph2->initiator, ph2->tunnel->peer->life_check ) ) continue; // // we found a proposal and transform // match for this entry of a bundle, // add them to our temporary lists // plist_l.add( lproposal, true ); plist_r.add( rproposal, true ); ptmatch = true; } } } } } // // if the temporary proposal list // contains the same entry count // as the local bundle, we found // a match // if( plist_l.count() == lpcount ) { ph2->plist_l.clean(); ph2->plist_r.clean(); long lpindex = 0; long rpindex = 0; long tcount; long tindex; while( true ) { IKE_PROPOSAL * lproposal; IKE_PROPOSAL * rproposal; if( ( !plist_l.nextp( &lproposal, lpindex, tindex, tcount ) ) || ( !plist_r.nextp( &rproposal, rpindex, tindex, tcount ) ) ) break; // // set protocol and transform number // lproposal->pnumb = rproposal->pnumb; lproposal->tnumb = rproposal->tnumb; // // check and potentialy modify lifetime // values if we are the responder // if( !ph2->initiator ) { switch( ph2->tunnel->peer->life_check ) { case LTIME_OBEY: { // // always use the initiators // if( lproposal->life_sec != rproposal->life_sec ) { log.txt( LLOG_INFO, "ii : adjusting %s lifetime %i -> %i ( obey )\n", find_name( NAME_PROTOCOL, lproposal->proto ), lproposal->life_sec, rproposal->life_sec ); lproposal->life_sec = rproposal->life_sec; } } case LTIME_CLAIM: { // // use initiators when shorter // if( lproposal->life_sec > rproposal->life_sec ) { log.txt( LLOG_INFO, "ii : adjusting %s lifetime %i -> %i ( claim )\n", find_name( NAME_PROTOCOL, lproposal->proto ), lproposal->life_sec, rproposal->life_sec ); lproposal->life_sec = rproposal->life_sec; } // // use responders when shorter, log and notify // if( lproposal->life_sec < rproposal->life_sec ) { log.txt( LLOG_INFO, "ii : using responder %s lifetime %i seconds, initiators is longer ( claim )\n", find_name( NAME_PROTOCOL, lproposal->proto ), lproposal->life_sec ); ph2->lstate |= LSTATE_CLAIMLT; } } case LTIME_STRICT: { // // use initiators when shorter // if( lproposal->life_sec > rproposal->life_sec ) { log.txt( LLOG_INFO, "ii : adjusting %s lifetime %i -> %i ( strict )\n", find_name( NAME_PROTOCOL, lproposal->proto ), lproposal->life_sec, rproposal->life_sec ); lproposal->life_sec = rproposal->life_sec; } } } } // // add to our permanent list // ph2->plist_l.add( lproposal, true ); ph2->plist_r.add( rproposal, true ); } return LIBIKE_OK; } } return LIBIKE_FAILED; } bool _IKED::phase2_cmp_prop( IKE_PROPOSAL * proposal1, IKE_PROPOSAL * proposal2, bool initiator, long life_check ) { // // check proposal protocol // if( proposal1->proto != proposal2->proto ) { log.txt( LLOG_DEBUG, "ii : unmatched proposal protocol\n" "ii : protocol ( %s != %s )\n", find_name( NAME_PROTOCOL, proposal1->proto ), find_name( NAME_PROTOCOL, proposal2->proto ) ); return false; } // // validate phase2 protocol // long xtype = 0; long htype = NAME_MAUTH; switch( proposal2->proto ) { case ISAKMP_PROTO_IPSEC_AH: xtype = NAME_XFORM_AH; break; case ISAKMP_PROTO_IPSEC_ESP: xtype = NAME_XFORM_ESP; break; case ISAKMP_PROTO_IPCOMP: xtype = NAME_XFORM_IPCOMP; break; default: { log.txt( LLOG_ERROR, "!! : internal error, phase2 protocol unknown %i\n", proposal2->proto ); return false; } } // // check proposal transform type // if( proposal1->xform != proposal2->xform ) { log.txt( LLOG_DEBUG, "ii : unmatched %s proposal/transform\n" "ii : crypto transform type ( %s != %s )\n", find_name( NAME_PROTOCOL, proposal1->proto ), find_name( xtype, proposal1->xform ), find_name( xtype, proposal2->xform ) ); return false; } // // check transform key legth // if( proposal1->ciph_kl != proposal2->ciph_kl ) { log.txt( LLOG_DEBUG, "ii : unmatched %s proposal/transform\n" "ii : key length ( %i != %i )\n", find_name( NAME_PROTOCOL, proposal1->proto ), proposal1->ciph_kl, proposal2->ciph_kl ); return false; } // // check proposal encap mode // if( proposal1->encap != proposal2->encap ) { log.txt( LLOG_DEBUG, "ii : unmatched %s proposal/transform\n" "ii : encapsulation mode ( %s != %s )\n", find_name( NAME_PROTOCOL, proposal1->proto ), find_name( NAME_ENCAP, proposal1->encap ), find_name( NAME_ENCAP, proposal2->encap ) ); return false; } // // check message auth selection // if( proposal1->hash_id != proposal2->hash_id ) { log.txt( LLOG_DEBUG, "ii : unmatched %s proposal/transform\n" "ii : msg auth ( %s != %s )\n", find_name( NAME_PROTOCOL, proposal1->proto ), find_name( htype, proposal1->hash_id ), find_name( htype, proposal2->hash_id ) ); return false; } // // check pfs dh group description // if( proposal1->dhgr_id != proposal2->dhgr_id ) { log.txt( LLOG_DEBUG, "ii : unmatched %s proposal/transform\n" "ii : pfs dh group description ( %s != %s )\n", find_name( NAME_PROTOCOL, proposal1->proto ), find_name( NAME_GROUP, proposal1->dhgr_id ), find_name( NAME_GROUP, proposal2->dhgr_id ) ); return false; } // // check lifetime values // if( !initiator ) { switch( life_check ) { case LTIME_OBEY: case LTIME_CLAIM: break; case LTIME_STRICT: { if( proposal1->life_sec < proposal2->life_sec ) { log.txt( LLOG_DEBUG, "ii : unmatched %s proposal/transform\n" "ii : lifetime seconds ( %i < %i strict )\n", find_name( NAME_PROTOCOL, proposal1->proto ), proposal1->life_sec, proposal2->life_sec ); return false; } break; } case LTIME_EXACT: { if( proposal1->life_sec != proposal2->life_sec ) { log.txt( LLOG_DEBUG, "ii : unmatched %s proposal/transform\n" "ii : lifetime seconds ( %i != %i exact )\n", find_name( NAME_PROTOCOL, proposal1->proto ), proposal1->life_sec, proposal2->life_sec ); return false; } break; } } } // // check peer for RFC compliance // if( initiator ) { if( proposal1->pnumb != proposal2->pnumb ) log.txt( LLOG_ERROR, "!! : peer violates RFC, proposal number mismatch ( %i != %i )\n", proposal1->pnumb, proposal2->pnumb ); if( proposal1->tnumb != proposal2->tnumb ) log.txt( LLOG_ERROR, "!! : peer violates RFC, transform number mismatch ( %i != %i )\n", proposal1->tnumb, proposal2->tnumb ); } // // proposal and transform matched // char klentxt[ 32 ]; if( proposal1->ciph_kl ) sprintf_s( klentxt, 32, "%i bits", proposal1->ciph_kl ); else sprintf_s( klentxt, 32, "default" ); log.txt( LLOG_INFO, "ii : matched %s proposal #%i transform #%i\n" "ii : - transform = %s\n" "ii : - key length = %s\n" "ii : - encap mode = %s\n" "ii : - msg auth = %s\n" "ii : - pfs dh group = %s\n" "ii : - life seconds = %i\n" "ii : - life kbytes = %i\n", find_name( NAME_PROTOCOL, proposal1->proto ), proposal2->pnumb, proposal2->tnumb, find_name( xtype, proposal1->xform ), klentxt, find_name( NAME_ENCAP, proposal1->encap ), find_name( NAME_MAUTH, proposal1->hash_id ), find_name( NAME_GROUP, proposal1->dhgr_id ), proposal1->life_sec, proposal1->life_kbs ); return true; } ike-2.2.1+dfsg/source/iked/ike.socket.cpp000066400000000000000000000465661223036517100202030ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "iked.h" // // UNIX socket code // long _IKED::socket_init() { socketpair( AF_UNIX, SOCK_STREAM, 0, wake_socket ); fcntl( wake_socket[ 0 ], F_SETFL, O_NONBLOCK ); return LIBIKE_OK; } void _IKED::socket_done() { while( list_socket.count() ) { SOCK_INFO * sock_info = static_cast( list_socket.del_entry( 0 ) ); close( sock_info->sock ); delete sock_info; } } long _IKED::socket_create( IKE_SADDR & saddr, bool natt ) { SOCK_INFO * sock_info = new SOCK_INFO; if( sock_info == NULL ) return LIBIKE_SOCKET; sock_info->saddr = saddr; sock_info->natt = natt; sock_info->sock = socket( PF_INET, SOCK_DGRAM, 0 ); if( sock_info->sock < 0 ) { log.txt( LLOG_ERROR, "!! : socket create failed\n" ); return LIBIKE_SOCKET; } struct linger linger = { 0, 0 }; if( setsockopt( sock_info->sock, SOL_SOCKET, SO_LINGER, &linger, sizeof( linger ) ) < 0 ) { log.txt( LLOG_ERROR, "!! : socket set linger option failed\n" ); return LIBIKE_SOCKET; } int optval = 1; if( setsockopt( sock_info->sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof( optval ) ) < 0 ) { log.txt( LLOG_ERROR, "!! : socket set linger option failed\n" ); return LIBIKE_SOCKET; } #ifdef __linux__ optval = 1; if( setsockopt( sock_info->sock, IPPROTO_IP, IP_PKTINFO, &optval, sizeof( optval ) ) < 0) { log.txt( LLOG_ERROR, "!! : socket set recvdstaddr option failed\n" ); return LIBIKE_SOCKET; } #else optval = 1; if( setsockopt( sock_info->sock, IPPROTO_IP, IP_RECVDSTADDR, &optval, sizeof( optval ) ) < 0) { log.txt( LLOG_ERROR, "!! : socket set recvdstaddr option failed\n" ); return LIBIKE_SOCKET; } #endif if( bind( sock_info->sock, &sock_info->saddr.saddr, sizeof( sock_info->saddr.saddr4 ) ) < 0 ) { log.txt( LLOG_ERROR, "!! : socket bind failed\n" ); return LIBIKE_SOCKET; } #if defined( OPT_NATT ) && !defined( __APPLE__ ) if( natt ) { optval = UDP_ENCAP_ESPINUDP; if( setsockopt( sock_info->sock, SOL_UDP, UDP_ENCAP, &optval, sizeof( optval ) ) < 0) { log.txt( LLOG_ERROR, "!! : socket set udp-encap non-esp option failed\n" ); return LIBIKE_SOCKET; } } else { optval = UDP_ENCAP_ESPINUDP_NON_IKE; if( setsockopt( sock_info->sock, SOL_UDP, UDP_ENCAP, &optval, sizeof( optval ) ) < 0) { log.txt( LLOG_ERROR, "!! : socket set udp-encap non-ike option failed\n" ); return LIBIKE_SOCKET; } } #endif lock_net.lock(); list_socket.add_entry( sock_info ); lock_net.unlock(); char txtaddr[ LIBIKE_MAX_TEXTADDR ]; iked.text_addr( txtaddr, &saddr, true ); if( natt ) { log.txt( LLOG_INFO, "ii : created natt socket %s\n", txtaddr ); sock_natt_open++; } else { log.txt( LLOG_INFO, "ii : created ike socket %s\n", txtaddr ); sock_ike_open++; } return LIBIKE_OK; } void _IKED::socket_wakeup() { char c = 0; send( wake_socket[ 1 ], &c, 1, 0 ); } long _IKED::socket_lookup_addr( IKE_SADDR & saddr_r, IKE_SADDR & saddr_l ) { // // determine the best interface and local // address to reach a remote host address // IPROUTE_ENTRY entry; entry.addr = saddr_r.saddr4.sin_addr; if( !iproute.best( entry ) ) { char txtaddr[ LIBIKE_MAX_TEXTADDR ]; text_addr( txtaddr, &saddr_r, true ); log.txt( LLOG_DEBUG, "ii : unable to select local address for peer %s\n", txtaddr ); return LIBIKE_SOCKET; } saddr_l.saddr4.sin_family = AF_INET; saddr_l.saddr4.sin_addr = entry.iface; char txtaddr[ LIBIKE_MAX_TEXTADDR ]; text_addr( txtaddr, &saddr_l, false ); log.txt( LLOG_DEBUG, "ii : local address %s selected for peer\n", txtaddr ); return LIBIKE_OK; } long _IKED::socket_lookup_port( IKE_SADDR & saddr_l, bool natt ) { // // locate a locally bound socket port for // the specified local address and type // long count = list_socket.count(); long index = 0; for( ; index < count; index++ ) { SOCK_INFO * sock_info = static_cast( list_socket.get_entry( index ) ); if( has_sockaddr( &sock_info->saddr.saddr ) ) if( cmp_sockaddr( sock_info->saddr.saddr, saddr_l.saddr, false ) ) continue; if( sock_info->natt != natt ) continue; u_int16_t port; get_sockport( sock_info->saddr.saddr, port ); set_sockport( saddr_l.saddr, port ); return LIBIKE_OK; } return LIBIKE_SOCKET; } long _IKED::header( PACKET_IP & packet, ETH_HEADER & header ) { // // set the header protocol // header.prot = htons( PROTO_IP ); return LIBIKE_OK; } long _IKED::recv_ip( PACKET_IP & packet, ETH_HEADER * ethhdr ) { fd_set fdset; FD_ZERO( &fdset ); lock_net.lock(); long count = list_socket.count(); long index = 0; int hival = wake_socket[ 0 ]; FD_SET( wake_socket[ 0 ], &fdset ); for( ; index < count; index++ ) { SOCK_INFO * sock_info = static_cast( list_socket.get_entry( index ) ); FD_SET( sock_info->sock, &fdset ); if( hival < sock_info->sock ) hival = sock_info->sock; } long result = select( hival + 1, &fdset, NULL, NULL, NULL ); lock_net.unlock(); if( result < 0 ) return LIBIKE_SOCKET; if( FD_ISSET( wake_socket[ 0 ], &fdset ) ) return LIBIKE_SOCKET; // // recv packet data // IKE_SADDR from; IKE_SADDR dest; socklen_t flen = sizeof( from.saddr4 ); for( index = 0; index < count; index++ ) { SOCK_INFO * sock_info = static_cast( list_socket.get_entry( index ) ); if( FD_ISSET( sock_info->sock, &fdset ) == 0 ) continue; unsigned char buff[ RAWNET_BUFF_SIZE ]; unsigned char ctrl[ 256 ]; iovec iov; iov.iov_base = buff; iov.iov_len = RAWNET_BUFF_SIZE; msghdr msg; msg.msg_name = (caddr_t)&from; msg.msg_namelen = flen; msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = ctrl; msg.msg_controllen = 256; msg.msg_flags = 0; long result = recvmsg( sock_info->sock, &msg, 0 ); if( result <= 0 ) continue; #ifdef __linux__ struct cmsghdr *cm; cm = (struct cmsghdr *) ctrl; struct in_pktinfo * pi; pi = ( struct in_pktinfo * )( CMSG_DATA( cm ) ); memcpy( &dest.saddr4.sin_addr, &pi->ipi_addr, sizeof( dest.saddr4.sin_addr ) ); #else memcpy( &dest.saddr4.sin_addr, CMSG_DATA( msg.msg_control ), sizeof( dest.saddr4.sin_addr ) ); #endif // // add udp and ip headers // PACKET_UDP packet_udp; packet_udp.write( from.saddr4.sin_port, sock_info->saddr.saddr4.sin_port ); packet_udp.add( buff, result ); packet_udp.done( from.saddr4.sin_addr, dest.saddr4.sin_addr ); packet.write( from.saddr4.sin_addr, dest.saddr4.sin_addr, 0, PROTO_IP_UDP ); packet.add( packet_udp ); packet.done(); // // optionally return an ethernet // header for this packet // if( ethhdr != NULL ) { result = header( packet, *ethhdr ); if( result == LIBIKE_SOCKET ) return LIBIKE_SOCKET; } return LIBIKE_OK; } return LIBIKE_NODATA; } long _IKED::send_ip( PACKET_IP & packet, ETH_HEADER * ethhdr ) { // // read ip packet // IKE_SADDR saddr_src; IKE_SADDR saddr_dst; unsigned char prot; memset( &saddr_src, 0, sizeof( saddr_src ) ); memset( &saddr_dst, 0, sizeof( saddr_dst ) ); saddr_src.saddr4.sin_family = AF_INET; saddr_dst.saddr4.sin_family = AF_INET; packet.read( saddr_src.saddr4.sin_addr, saddr_dst.saddr4.sin_addr, prot ); // // read udp packet // PACKET_UDP packet_udp; packet.get( packet_udp ); packet_udp.read( saddr_src.saddr4.sin_port, saddr_dst.saddr4.sin_port ); long count = list_socket.count(); long index = 0; for( ; index < count; index++ ) { SOCK_INFO * sock_info = static_cast( list_socket.get_entry( index ) ); if( has_sockaddr( &sock_info->saddr.saddr ) ) { if( !cmp_sockaddr( sock_info->saddr.saddr, saddr_src.saddr, true ) ) continue; } else { u_int16_t port1; u_int16_t port2; get_sockport( sock_info->saddr.saddr, port1 ); get_sockport( saddr_src.saddr, port2 ); if( port1 != port2 ) continue; } // // send packet data // long result = sendto( sock_info->sock, packet_udp.buff() + packet_udp.oset(), packet_udp.size() - packet_udp.oset(), 0, &saddr_dst.saddr, sizeof( saddr_dst.saddr4 ) ); if( result <= 0 ) { log.txt( LLOG_ERROR, "!! : send error %li\n", result ); return LIBIKE_SOCKET; } // // optionally return an ethernet // header for this packet // if( ethhdr != NULL ) { result = header( packet, *ethhdr ); if( result == LIBIKE_SOCKET ) return LIBIKE_SOCKET; } return LIBIKE_OK; } log.txt( LLOG_ERROR, "!! : socket not found\n" ); return LIBIKE_SOCKET; } // // UNIX virtual adapter code // bool _IKED::vnet_init() { #ifdef __FreeBSD__ kldload( "/boot/kernel/if_tap.ko" ); return true; #endif return false; } bool _IKED::vnet_get( VNET_ADAPTER ** adapter ) { // create adapter struct *adapter = new VNET_ADAPTER; if( !*adapter ) return false; #if defined( __FreeBSD__ ) || defined( __APPLE__ ) // find existing device int index = 0; for( ; index < 16; index++ ) { // check for existing device struct stat sb; sprintf( (*adapter)->name, "/dev/tap%i" , index ); // attempt to stat device if( stat( (*adapter)->name, &sb ) ) { log.txt( LLOG_DEBUG, "ii : unable to stat %s\n", (*adapter)->name ); break; } // attempt to open device (*adapter)->fn = open( (*adapter)->name, O_RDWR ); if( (*adapter)->fn == -1 ) { log.txt( LLOG_DEBUG, "ii : unable to open %s\n", (*adapter)->name ); continue; } sprintf( (*adapter)->name, "tap%i" , index ); break; } if( (*adapter)->fn == -1 ) { // create new device (*adapter)->fn = open( "/dev/tap", O_RDWR); if( (*adapter)->fn == -1 ) { log.txt( LLOG_ERROR, "!! : failed to open tap device\n" ); delete *adapter; *adapter = NULL; return false; } struct stat buf; if( fstat( (*adapter)->fn, &buf ) < 0 ) { log.txt( LLOG_ERROR, "!! : failed to read tap interface name\n" ); close( (*adapter)->fn ); delete *adapter; *adapter = NULL; return false; } devname_r( buf.st_rdev, S_IFCHR, (*adapter)->name, IFNAMSIZ ); } #endif #ifdef __NetBSD__ (*adapter)->fn = open( "/dev/tap", O_RDWR); if( (*adapter)->fn == -1 ) { log.txt( LLOG_ERROR, "!! : failed to open tap device\n" ); delete *adapter; *adapter = NULL; return false; } struct ifreq ifr; memset( &ifr, 0, sizeof( ifr ) ); if( ioctl( (*adapter)->fn, TAPGIFNAME, (void*) &ifr ) < 0 ) { log.txt( LLOG_ERROR, "!! : failed to read tap interface name\n" ); close( (*adapter)->fn ); delete *adapter; *adapter = NULL; return false; } strcpy( (*adapter)->name, ifr.ifr_name ); #endif #ifdef __linux__ (*adapter)->fn = open( "/dev/net/tun", O_RDWR); if( (*adapter)->fn == -1 ) { log.txt( LLOG_ERROR, "!! : failed to open tap device\n" ); delete *adapter; *adapter = NULL; return false; } struct ifreq ifr; memset( &ifr, 0, sizeof( ifr ) ); ifr.ifr_flags = IFF_TAP | IFF_NO_PI; if( ioctl( (*adapter)->fn, TUNSETIFF, (void*) &ifr ) < 0 ) { log.txt( LLOG_ERROR, "!! : failed to get tap interface name\n" ); close( (*adapter)->fn ); delete *adapter; *adapter = NULL; return false; } strcpy( (*adapter)->name, ifr.ifr_name ); #endif log.txt( LLOG_INFO, "ii : opened tap device %s\n", (*adapter)->name ); return true; } bool _IKED::vnet_rel( VNET_ADAPTER * adapter ) { // close adapter if( adapter->fn != -1 ) close( adapter->fn ); log.txt( LLOG_INFO, "ii : closed tap device %s\n", adapter->name ); // free adapter struct delete adapter; return true; } bool _IKED::client_net_config( IDB_TUNNEL * tunnel ) { if( tunnel->xconf.opts & IPSEC_OPTS_ADDR ) { // // acquire virtual adapter // if( !vnet_get( &tunnel->adapter ) ) { log.txt( LLOG_ERROR, "ii : unable to create tap adapter ...\n" ); return false; } // // open socket for configuration // int sock = socket( PF_INET, SOCK_DGRAM, 0 ); if( sock == -1 ) { log.txt( LLOG_ERROR, "!! : failed to create adapter socket ( %s )\n", strerror( errno ) ); return false; } // // bring interface down // struct ifreq ifr; memset( &ifr, 0, sizeof( struct ifreq ) ); strncpy( ifr.ifr_name, tunnel->adapter->name, IFNAMSIZ ); if( ioctl( sock, SIOCGIFFLAGS, &ifr ) < 0 ) { log.txt( LLOG_ERROR, "!! : failed to get interface flags %s for ( %s )\n", tunnel->adapter->name, strerror( errno ) ); close( sock ); return false; } ifr.ifr_flags &= IFF_UP; if( ioctl( sock, SIOCSIFFLAGS, &ifr ) < 0 ) { log.txt( LLOG_ERROR, "!! : failed to set interface flags %s for ( %s )\n", tunnel->adapter->name, strerror( errno ) ); close( sock ); return false; } #ifdef __linux__ // // configure internet addresses // struct sockaddr_in * addr = ( struct sockaddr_in * ) &( ifr.ifr_addr ); addr->sin_family = AF_INET; addr->sin_addr = tunnel->xconf.addr; if( ioctl( sock, SIOCSIFADDR, &ifr ) != 0 ) { log.txt( LLOG_ERROR, "!! : failed to configure address for %s ( %s )\n", tunnel->adapter->name, strerror( errno ) ); close( sock ); return false; } // // configure netmask addresses // addr->sin_addr = tunnel->xconf.mask; if( ioctl( sock, SIOCSIFNETMASK, &ifr ) != 0 ) { log.txt( LLOG_ERROR, "!! : failed to configure netmask for %s ( %s )\n", tunnel->adapter->name, strerror( errno ) ); close( sock ); return false; } // // configure broadcast addresses // addr->sin_addr.s_addr = tunnel->xconf.addr.s_addr; addr->sin_addr.s_addr &= tunnel->xconf.mask.s_addr; addr->sin_addr.s_addr |= ~tunnel->xconf.mask.s_addr; if( ioctl( sock, SIOCSIFBRDADDR, &ifr ) != 0 ) { log.txt( LLOG_ERROR, "!! : failed to configure broadcast address for %s ( %s )\n", tunnel->adapter->name, strerror( errno ) ); close( sock ); return false; } #else // // configure internet, netmask and broadcast addresses // struct ifaliasreq ifra; memset( &ifra, 0, sizeof( struct ifaliasreq ) ); strncpy( ifra.ifra_name, tunnel->adapter->name, IFNAMSIZ ); struct sockaddr_in * addr = ( struct sockaddr_in * ) &( ifra.ifra_addr ); addr->sin_family = AF_INET; SET_SALEN( addr, sizeof( struct sockaddr_in ) ); addr->sin_addr = tunnel->xconf.addr; struct sockaddr_in * mask = ( struct sockaddr_in * ) &( ifra.ifra_mask ); mask->sin_family = AF_INET; SET_SALEN( mask, sizeof( struct sockaddr_in ) ); mask->sin_addr = tunnel->xconf.mask; struct sockaddr_in * bcst = ( struct sockaddr_in * ) &( ifra.ifra_broadaddr ); bcst->sin_family = AF_INET; SET_SALEN( bcst, sizeof( struct sockaddr_in ) ); bcst->sin_addr.s_addr = tunnel->xconf.addr.s_addr; bcst->sin_addr.s_addr &= tunnel->xconf.mask.s_addr; bcst->sin_addr.s_addr |= ~tunnel->xconf.mask.s_addr; if( ioctl( sock, SIOCAIFADDR, &ifra ) < 0 ) { log.txt( LLOG_ERROR, "!! : failed to configure address for %s ( %s )\n", tunnel->adapter->name, strerror( errno ) ); close( sock ); return false; } #endif // // configure mtu // ifr.ifr_mtu = tunnel->xconf.vmtu; if( ioctl( sock, SIOCSIFMTU, &ifr ) != 0 ) { log.txt( LLOG_ERROR, "!! : failed to configure MTU for %s ( %s )\n", tunnel->adapter->name, strerror( errno ) ); close( sock ); return false; } // // bring interface up // if( ioctl( sock, SIOCGIFFLAGS, &ifr ) < 0 ) { log.txt( LLOG_ERROR, "!! : failed to get interface flags for %s ( %s )\n", tunnel->adapter->name, strerror( errno ) ); close( sock ); return false; } ifr.ifr_flags |= IFF_UP; if( ioctl( sock, SIOCSIFFLAGS, &ifr ) < 0 ) { log.txt( LLOG_ERROR, "!! : failed to set interface flags for %s ( %s )\n", tunnel->adapter->name, strerror( errno ) ); close( sock ); return false; } close( sock ); log.txt( LLOG_INFO, "ii : configured adapter %s\n", tunnel->adapter->name ); } return true; } bool _IKED::client_net_revert( IDB_TUNNEL * tunnel ) { if( tunnel->xconf.opts & IPSEC_OPTS_ADDR ) { if( tunnel->adapter != NULL ) { vnet_rel( tunnel->adapter ); tunnel->adapter = NULL; } } return true; } bool _IKED::client_dns_config( IDB_TUNNEL * tunnel ) { if( tunnel->xconf.opts & ( IPSEC_OPTS_DNSS | IPSEC_OPTS_DOMAIN ) ) { // backup the current resolv.conf file rename( "/etc/resolv.conf", "/etc/resolv.iked" ); FILE * fp1 = fopen( "/etc/resolv.iked", "r" ); FILE * fp2 = fopen( "/etc/resolv.conf", "w+" ); if( fp2 != NULL ) { // write configuration if( tunnel->xconf.opts & IPSEC_OPTS_DOMAIN ) fprintf( fp2, "domain\t%s\n", tunnel->xconf.nscfg.dnss_suffix ); if( tunnel->xconf.opts & IPSEC_OPTS_DNSS ) for( int i = 0; i < tunnel->xconf.nscfg.dnss_count; i++ ) fprintf( fp2, "nameserver\t%s\n", inet_ntoa( tunnel->xconf.nscfg.dnss_list[ i ] ) ); if( fp1 != NULL ) { // merge additional options char line[ 1024 ]; while( fgets( line, sizeof( line ), fp1 ) != NULL ) { if( !strncmp( line, "domain", 6 ) ) { if( !( tunnel->xconf.opts & IPSEC_OPTS_DOMAIN ) ) fwrite( line, strlen( line ), 1, fp2 ); continue; } if( !strncmp( line, "nameserver", 9 ) ) { if( !( tunnel->xconf.opts & IPSEC_OPTS_DNSS ) ) fwrite( line, strlen( line ), 1, fp2 ); continue; } fwrite( line, strlen( line ), 1, fp2 ); } fclose( fp1 ); } fclose( fp2 ); } } return true; } bool _IKED::client_dns_revert( IDB_TUNNEL * tunnel ) { if( tunnel->xconf.opts & ( IPSEC_OPTS_DNSS | IPSEC_OPTS_DOMAIN ) ) { // restore the previous resolv.conf file rename( "/etc/resolv.iked", "/etc/resolv.conf" ); } return true; } ike-2.2.1+dfsg/source/iked/ike.xauth.cpp000066400000000000000000000226101223036517100200240ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "iked.h" // // XAUTH - BASE CLASS // _IKED_XAUTH::~_IKED_XAUTH() { } // // XAUTH - LOCAL ACCOUNT DB // static const char * iked_xauth_local_name = "local"; _IKED_XAUTH_LOCAL::_IKED_XAUTH_LOCAL() { } _IKED_XAUTH_LOCAL::~_IKED_XAUTH_LOCAL() { } const char * _IKED_XAUTH_LOCAL::name() { return iked_xauth_local_name; } bool _IKED_XAUTH_LOCAL::auth_pwd( IKE_XAUTH & xauth ) { // // null terminate username and password // xauth.user.add( 0, 1 ); xauth.pass.add( 0, 1 ); const char * usr = ( const char * ) xauth.user.buff(); const char * pwd = ( const char * ) xauth.pass.buff(); #ifdef UNIX struct passwd * pw = getpwnam( usr ); if( pw == NULL ) return false; if( pw->pw_uid == 0 ) return false; #ifdef OPT_SHADOW struct spwd * spw = getspnam( usr ); if( spw == NULL ) return false; char * syscryptpwd = spw->sp_pwdp; #else char * syscryptpwd = pw->pw_passwd; #endif char * cryptpwd = crypt( pwd, syscryptpwd ); if( cryptpwd == NULL ) return false; if( !strcmp( cryptpwd, syscryptpwd ) ) return true; #endif return false; } bool _IKED_XAUTH_LOCAL::auth_grp( IKE_XAUTH & xauth, BDATA & group ) { #ifdef UNIX const char * usr = ( const char * ) xauth.user.buff(); const char * grp = ( const char * ) group.buff(); struct group * gr = getgrnam( grp ); if( gr == NULL ) return false; char * member; int index = 0; while( ( member = gr->gr_mem[ index++ ] ) != NULL ) if( !strcmp( member, usr ) ) return true; #endif return false; } // // XAUTH - LDAP ACCOUNT DB // #ifdef OPT_LDAP static const char * iked_xauth_ldap_name = "ldap"; _IKED_XAUTH_LDAP::_IKED_XAUTH_LDAP() { // // set ldap defaults // version = 3; subtree = false; attr_user.set( "cn", strlen( "cn" ) + 1 ); attr_group.set( "cn", strlen( "cn" ) + 1 ); attr_member.set( "member", strlen( "member" ) + 1 ); } _IKED_XAUTH_LDAP::~_IKED_XAUTH_LDAP() { } const char * _IKED_XAUTH_LDAP::name() { return iked_xauth_ldap_name; } bool _IKED_XAUTH_LDAP::open_conn( LDAP ** ld ) { // initialize the ldap handle int res = ldap_initialize( ld, url.text() ); if( res != LDAP_SUCCESS ) { iked.log.txt( LLOG_ERROR, "!! : xauth ldap initialize failed ( %s )\n", ldap_err2string( res ) ); return false; } // initialize the protocol version ldap_set_option( *ld, LDAP_OPT_PROTOCOL_VERSION, &version ); // // attempt to bind to the ldap server. // default to anonymous bind unless a // user dn and password has been // specified in our configuration // if( bind_dn.size() && bind_pw.size() ) { struct berval cred; cred.bv_val = bind_pw.text(); cred.bv_len = bind_pw.size() - 1; res = ldap_sasl_bind_s( *ld, bind_dn.text(), NULL, &cred, NULL, NULL, NULL ); } else { res = ldap_sasl_bind_s( *ld, NULL, NULL, NULL, NULL, NULL, NULL ); } if( res != LDAP_SUCCESS ) { iked.log.txt( LLOG_ERROR, "!! : xauth ldap search bind failed ( %s )\n", ldap_err2string( res ) ); ldap_unbind_ext_s( *ld, NULL, NULL ); return false; } return true; } bool _IKED_XAUTH_LDAP::auth_pwd( IKE_XAUTH & xauth ) { bool result = false; LDAP * ld = NULL; BDATA filter; char * atlist[ 1 ] = { NULL }; char * userdn = NULL; int scope = LDAP_SCOPE_ONELEVEL; int ecount = 0; LDAPMessage * lr = NULL; LDAPMessage * le = NULL; // open an ldap connection if( !open_conn( &ld ) ) return false; // build an ldap user search filter filter.add( attr_user.buff(), attr_user.size() - 1 ); filter.add( "=", 1 ); filter.add( xauth.user.buff(), xauth.user.size() - 1 ); filter.add( 0, 1 ); // attempt to locate the user dn if( subtree ) scope = LDAP_SCOPE_SUBTREE; struct timeval timeout; timeout.tv_sec = 15; timeout.tv_usec = 0; int res = ldap_search_ext_s( ld, base.text(), scope, filter.text(), atlist, 0, NULL, NULL, &timeout, 2, &lr ); if( res != LDAP_SUCCESS ) { iked.log.txt( LLOG_ERROR, "!! : xauth ldap user search failed ( %s )\n", ldap_err2string( res ) ); goto ldap_pwd_end; } // check the number of ldap entries returned ecount = ldap_count_entries(ld, lr); if( ecount < 1 ) goto ldap_pwd_end; if( ecount > 1 ) { iked.log.txt( LLOG_ERROR, "!! : warning, ldap return multiple results for user %s\n", xauth.user.buff() ); } // obtain the first result entry le = ldap_first_entry( ld, lr ); if( le == NULL ) { iked.log.txt( LLOG_ERROR, "!! : xauth ldap unable to read result entry" ); goto ldap_pwd_end; } // obtain the result entry dn userdn = ldap_get_dn( ld, le ); if( userdn == NULL ) { iked.log.txt( LLOG_ERROR, "!! : xauth ldap unable to read result dn" ); goto ldap_pwd_end; } // cache the user dn in the xauth state xauth.context.set( userdn, strlen( userdn ) + 1 ); // // finally, use the dn and the xauth // password to check the users given // credentials by attempting to bind // to the ldap server // struct berval cred; cred.bv_val = ( char * ) xauth.pass.buff(); cred.bv_len = xauth.pass.size() - 1; res = ldap_sasl_bind_s( ld, userdn, NULL, &cred, NULL, NULL, NULL); if( res == LDAP_SUCCESS ) result = true; ldap_pwd_end: // free ldap resources if( userdn != NULL ) ldap_memfree( userdn ); if( lr != NULL ) ldap_msgfree( lr ); ldap_unbind_ext_s( ld, NULL, NULL ); return result; } bool _IKED_XAUTH_LDAP::auth_grp( IKE_XAUTH & xauth, BDATA & group ) { bool result = false; LDAP * ld = NULL; BDATA filter; char * atlist[ 1 ] = { NULL }; int scope = LDAP_SCOPE_ONELEVEL; int ecount = 0; LDAPMessage * lr = NULL; // open an ldap connection if( !open_conn( &ld ) ) return false; // build an ldap group search filter filter.add( "(&(", 3 ); filter.add( attr_group.buff(), attr_group.size() - 1 ); filter.add( "=", 1 ); filter.add( group.buff(), group.size() - 1 ); filter.add( ")(", 2 ); filter.add( attr_member.buff(), attr_member.size() - 1 ); filter.add( "=", 1 ); filter.add( xauth.context.buff(), xauth.context.size() - 1 ); filter.add( "))", 2 ); filter.add( 0, 1 ); // attempt to locate the group dn if( subtree ) scope = LDAP_SCOPE_SUBTREE; struct timeval timeout; timeout.tv_sec = 15; timeout.tv_usec = 0; int res = ldap_search_ext_s( ld, base.text(), scope, filter.text(), atlist, 0, NULL, NULL, &timeout, 2, &lr ); if( res != LDAP_SUCCESS ) { iked.log.txt( LLOG_ERROR, "!! : xauth ldap group search failed ( %s )\n", ldap_err2string( res ) ); goto ldap_grp_end; } // check the number of ldap entries returned ecount = ldap_count_entries( ld, lr ); if( ecount < 1 ) goto ldap_grp_end; if( ecount > 1 ) { iked.log.txt( LLOG_ERROR, "!! : warning, ldap return multiple results for group %s\n", group.buff() ); } // found a valid group membership result = true; ldap_grp_end: // free ldap resources if( lr != NULL ) ldap_msgfree( lr ); ldap_unbind_ext_s( ld, NULL, NULL ); return result; } #endif ike-2.2.1+dfsg/source/iked/ike.xconf.cpp000066400000000000000000000160301223036517100200070ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "iked.h" // // XCONF - BASE CLASS // _IKED_XCONF::~_IKED_XCONF() { delete [] pool4_array; } bool _IKED_XCONF::pool4_set( in_addr & base, long bits, long max ) { // // calculate network mask and addr // config.mask.s_addr = 0; for( long i = 0; i < bits; i++ ) { config.mask.s_addr >>= 1; config.mask.s_addr |= 0x80000000; } config.mask.s_addr = htonl( config.mask.s_addr ); config.addr.s_addr = base.s_addr & config.mask.s_addr; if( pool4_array != NULL ) delete [] pool4_array; // // calculate max total addresses // for the given network and the // first and last usable address // long len = ntohl( base.s_addr | ~config.mask.s_addr ) - ntohl( base.s_addr ) + 1; if( max ) { if( max <= len ) pool4_total = max; else pool4_total = len; } else pool4_total = len; in_addr last; last.s_addr = htonl( ntohl( base.s_addr ) + pool4_total - 1 ); static const char * adj = "( adjusted )"; static const char * org = ""; const char * adj_base = org; const char * adj_last = org; if( base.s_addr == config.addr.s_addr ) { if( max ) adj_base = adj; base.s_addr = htonl( ntohl( base.s_addr ) + 1 ); pool4_total--; } if( last.s_addr == ( base.s_addr | ~config.mask.s_addr ) ) { if( max ) adj_last = adj; last.s_addr = htonl( ntohl( last.s_addr ) - 1 ); pool4_total--; } // // create our address pool // pool4_array = new POOL4[ pool4_total ]; if( pool4_array == NULL ) return false; for( long a = 0; a < pool4_total; a++ ) { pool4_array[ a ].addr.s_addr = htonl( ntohl( base.s_addr ) + a ); pool4_array[ a ].used = false; } char txtaddr[ LIBIKE_MAX_TEXTADDR ]; char txtmask[ LIBIKE_MAX_TEXTADDR ]; char txtbase[ LIBIKE_MAX_TEXTADDR ]; char txtlast[ LIBIKE_MAX_TEXTADDR ]; iked.text_addr( txtaddr, config.addr ); iked.text_addr( txtmask, config.mask ); iked.text_addr( txtbase, base ); iked.text_addr( txtlast, last ); iked.log.txt( LLOG_DEBUG, "ii : created %s address pool\n" "ii : - network %s\n" "ii : - netmask %s\n" "ii : - base addr %s %s\n" "ii : - last addr %s %s\n" "ii : - available %i\n", name(), txtaddr, txtmask, txtbase, adj_base, txtlast, adj_last, pool4_total ); return true; } bool _IKED_XCONF::pool4_get( in_addr & addr ) { if( pool4_inuse == pool4_total ) return false; pool4_lock.lock(); long index = 0; for( ; index < pool4_total; index++ ) { if( !pool4_array[ index ].used ) { addr = pool4_array[ index ].addr; pool4_array[ index ].used = true; char txtaddr[ LIBIKE_MAX_TEXTADDR ]; iked.text_addr( txtaddr, addr ); iked.log.txt( LLOG_DEBUG, "ii : address %s aquired from %s pool\n", txtaddr, name() ); break; } } pool4_lock.unlock(); return ( index < pool4_total ); } bool _IKED_XCONF::pool4_rel( in_addr & addr ) { pool4_lock.lock(); long index = 0; for( ; index < pool4_total; index++ ) { if( pool4_array[ index ].used ) { if( addr.s_addr == pool4_array[ index ].addr.s_addr ) { pool4_array[ index ].used = false; char txtaddr[ LIBIKE_MAX_TEXTADDR ]; iked.text_addr( txtaddr, addr ); iked.log.txt( LLOG_DEBUG, "ii : address %s returned to %s pool\n", txtaddr, name() ); break; } } } pool4_lock.unlock(); return ( index < pool4_total ); } // // XCONF - LOCAL CONFIG DB // static const char * iked_xconf_local_name = "local"; _IKED_XCONF_LOCAL::_IKED_XCONF_LOCAL() { } _IKED_XCONF_LOCAL::~_IKED_XCONF_LOCAL() { } const char * _IKED_XCONF_LOCAL::name() { return iked_xconf_local_name; } bool _IKED_XCONF_LOCAL::rslt( IDB_TUNNEL * tunnel ) { tunnel->xconf.opts = tunnel->xconf.rqst; tunnel->xconf.opts &= config.opts; if( tunnel->xconf.opts & IPSEC_OPTS_ADDR ) pool4_get( tunnel->xconf.addr ); if( tunnel->xconf.opts & IPSEC_OPTS_MASK ) tunnel->xconf.mask = config.mask; if( tunnel->xconf.opts & IPSEC_OPTS_DNSS ) { memcpy( tunnel->xconf.nscfg.dnss_list, config.nscfg.dnss_list, sizeof( config.nscfg.dnss_list ) ); tunnel->xconf.nscfg.dnss_count = config.nscfg.dnss_count; } if( tunnel->xconf.opts & IPSEC_OPTS_DOMAIN ) memcpy( tunnel->xconf.nscfg.dnss_suffix, config.nscfg.dnss_suffix, CONF_STRLEN ); if( tunnel->xconf.opts & IPSEC_OPTS_SPLITDNS ) { BDATA suffix; long index = 0; while( domains.get( suffix, index++ ) ) tunnel->domains.add( suffix ); } if( tunnel->xconf.opts & IPSEC_OPTS_NBNS ) { memcpy( tunnel->xconf.nscfg.nbns_list, config.nscfg.nbns_list, sizeof( config.nscfg.nbns_list ) ); tunnel->xconf.nscfg.nbns_count = config.nscfg.nbns_count; } if( tunnel->xconf.opts & IPSEC_OPTS_PFS ) tunnel->xconf.dhgr = config.dhgr; if( tunnel->xconf.opts & IPSEC_OPTS_BANNER ) tunnel->banner.set( banner ); return true; } ike-2.2.1+dfsg/source/iked/iked.8000066400000000000000000000070031223036517100164240ustar00rootroot00000000000000.\" .\" Copyright (c) 2007 .\" Shrew Soft Inc. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" 3. Redistributions in any form must be accompanied by information on .\" how to obtain complete source code for the software and any .\" accompanying software that uses the software. The source code .\" must either be included in the distribution or be available for no .\" more than the cost of distribution plus a nominal fee, and must be .\" freely redistributable under reasonable conditions. For an .\" executable file, complete source code means the source code for all .\" modules it contains. It does not include source code for modules or .\" files that typically accompany the major components of the operating .\" system on which the executable file runs. .\" .\" THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS .\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED .\" WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR .\" NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC .\" 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. .\" .\" AUTHOR : Matthew Grooms .\" mgrooms@shrew.net .\" .\" .Dd Febuary 2, 2007 .Dt IKED 8 .Os .Sh NAME .Nm iked .Nd Internet Key Exchange Daemon .Sh SYNOPSIS .Nm .Op Fl f Ar cfgfile .Op Fl l Ar logfile .Op Fl d Ar level .Op Fl F .Sh DESCRIPTION The .Nm program communicates using the IKE protocol ( RFC 2409 ) to provide automatic keying for an IPsec capable host. The daemon communicates with the host os via PF_KEY ( RFC 2367 ) to obtain the local policy configuration and to receive key aquisition requests. The daemon is also capable of acting as a client or client gateway and can create appropriate IPsec policy entries on bahalf of the host or peer to faclilitate remote access IPsec VPN connectivity. For more informaiton, please see the .Xr ikea 1 and .Xr ikec 1 man pages. .Pp The options are as follows: .Bl -tag -width Fl .It Fl f Ar cfgfile Specify an alternate configuration file. .It Fl l Ar logfile Specify a log output file. .It Fl d Ar level Specify debug output level between 0-6. .It Fl p Ar pidfile Spefify a process id file. .It Fl F Run the program as a foreground application. .El .Sh RETURN VALUES The command exits with 0 on success, and non-zero on errors. .Sh FILES The default configuration file is .Pa /usr/local/etc/iked.conf .Sh SEE ALSO .Xr ikea 1 , .Xr ikec 1 , .Xr ipsec 4 , .Xr iked.conf 5 , .Xr setkey 8 .Sh HISTORY The .Nm program was written by Matthew Grooms ( mgrooms@shrew.net ) as part of the Shrew Soft ( http://www.shrew.net ) family of IPsec products. ike-2.2.1+dfsg/source/iked/iked.conf.5000066400000000000000000000564011223036517100173530ustar00rootroot00000000000000.\" .\" Copyright (c) 2007 .\" Shrew Soft Inc. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" 3. Redistributions in any form must be accompanied by information on .\" how to obtain complete source code for the software and any .\" accompanying software that uses the software. The source code .\" must either be included in the distribution or be available for no .\" more than the cost of distribution plus a nominal fee, and must be .\" freely redistributable under reasonable conditions. For an .\" executable file, complete source code means the source code for all .\" modules it contains. It does not include source code for modules or .\" files that typically accompany the major components of the operating .\" system on which the executable file runs. .\" .\" THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS .\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED .\" WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR .\" NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC .\" 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. .\" .\" AUTHOR : Matthew Grooms .\" mgrooms@shrew.net .\" .\" .Dd Febuary 2, 2007 .Dt IKED 8 .Os .Sh NAME .Nm iked.conf .Nd Internet Key Exchange Daemon Configuration File .Sh DESCRIPTION The .Nm file is used to configure .Xr iked 8 ( Internet Key Exchange Daemon ). The parameters supplied are used to negotiate ISAKMP ( phase1 ) and IPsec ( phase2 ) SAs for IPsec capable hosts. .Sh SYNTAX .Pp The configuration parameters are expressed as a series of sections containing a number of statements. Sections begin with a keyword optionally followed by a parameter list. All statements for a section are enclosed using the .Ql \&{ and .Ql \&} charachters. Statements begin with a keyword optionally followed by a parameter list and are terminated with the .Ql \&; charachter. Lines that begin with the .Ql \&# charachter are treated as comments. .Pp .Lp This document denotes keywords using .Ic this font and user supplied parameters using .Ar this font. Optional parameters are enclosed using the .Ql \&[ and .Ql \&] charachters. Multiple keywords that may be valid for a single parameter are enclosed using the .Ql \&( and .Ql \&) charachters and separated using the .Ql \&| charachter. .Pp The defined parameter types are as follows ... .Pp .Bl -tag -width addressx -compact .It Ar number A decimal number .It Ar label A string comprised of alphanumeric charachters .It Ar quoted A quoted string enclosed in .Ql \&" charachters .It Ar address An IP address expressed as x.x.x.x .It Ar network An IP network and prefix length expressed as x.x.x.x/y .El .Ss Daemon Section .Bl -tag -width Ds -compact .It Ic daemon { Ar statements Ic } Specifies the general configuration for .Xr iked 8 operation. This includes parameters related to the basic network configuration, log file and debug output. Only one .Ic daemon section should be defined. .Pp .Bl -tag -width Ds -compact .It Ic socket ( ike | natt ) Ar [ address ] number ; An address and port number that should be used for ike or natt communications. If the address parameter is omitted, the daemon will attempt to bind to any address for the given port number. If no socket statements are specified, the daemon will attempt to bind to all interfaces for both ike and natt using the default port numbers ( 500 & 4500 respectively ). Note, the .Ar natt keyword can only be specified if the daemon was compiled with natt support. .It Ic retry_count Ar number; The number of times an exchange packet should be resent to a peer. The default value for this parameter is 2. .It Ic retry_delay Ar number; The number of seconds to wait between packet resend attempts. The default value for this parameter is 10. .It Ic log_file Ar quoted ; The path and file name that should be used for log output. .It Ic log_level (none | error | info | debug | loud | decode) ; The log output detail level. The default value for this parameter is .Ic none . .It Ic pcap_decrypt Ar quoted; The path and file name that should be used to dump decrypted ike packets in pcap format. If no .Ic pcap_decrypt statement is specified, this feature is disabled. .It Ic pcap_encrypt Ar quoted; The path and file name that should be used to dump encrypted ike packets in pcap format. If no .Ic pcap_encrypt statement is specified, this feature is disabled. .It Ic dhcp_file Ar quoted; The path and file name that should be used to store a dhcp mac address seed value for dhcp over ipsec negotiation. If no file is present, the file will be created. .El .El .Ss Network Group Section .Bl -tag -width Ds -compact .It Ic netgroup Ar label Ic { Ar statements Ic } Specifies a group of networks that can be refferred to by the assigned label. Multiple .Ic netgroup sections may be defined. .Pp .Bl -tag -width Ds -compact .It Ic network ; A network to be associated with this network group. .El .El .Ss XAuth LDAP Section .Bl -tag -width Ds -compact .It Ic xauth_ldap { Ar statements Ic } Specifies the LDAP configuration to be used for when the .Ic xauth_source is set to .Ic ldap for a given peer section. Only one .Ic xauth_ldap section should be defined. Note, an .Ic xauth_ldap section can only be defined if the daemon was compiled with LDAP support. .Pp .Bl -tag -width Ds -compact .It Ic version Ar number ; The LDAP protocol version to be used ( 2 or 3 ). The default value for this parameter is 3. .It Ic url Ar quoted ; The LDAP server url. For example, a url may look like "ldap://ldap.shrew.net:389". .It Ic base Ar quoted ; The base dn to be used for LDAP searches. For example, a base dn may look like "ou=users,dc=shrew,dc=net". .It Ic subtree (enable | disable); The search scope to be used for LDAP searches. If enabled, searches will be performed using the subtree search scope. If disabled, searches will be performed using the one level search scope. The default value for this parameter is .Ic disable . .It Ic bind_dn Ar quoted; The dn to bind as before performing LDAP searches. If this parameter is omitted, searches will be performed using anonymous binds. .It Ic bind_pw Ar quoted; The password to use when a .Ic bind_dn is specified. .It Ic attr_user Ar quoted; The attribute used to specify a user name in the LDAP directory. For example, if a user dn is "cn=user,dc=shrew,dc=net" then the attribute would be "cn". The default value for this parameter is "cn". .It Ic attr_group Ar quoted; The attribute used to specify a group name in the LDAP directory. For example, if a group dn is "cn=group,dc=shrew,dc=net" then the attribute would be "cn". The default value for this parameter is "cn". .It Ic attr_member Ar quoted; The attribute used to specify a group member in the LDAP directory. The default value for this parameter is "member". .El .El .Ss XConf Local Section .Bl -tag -width Ds -compact .It Ic xconf_local { Ar statements Ic } Specifies the Configuration Exchange settings to be used when the .Ic xconf_source is set to .Ic local for a given peer section. Only one .Ic xconf_local section should be defined. .Pp .Bl -tag -width Ds -compact .It Ic network4 Ar network [number]; The network that will be used to define a local address pool. An optional number can be specified to restrict the pool to a specific size. An address from this pool along with the network mask are passed to a peer when requested. .It Ic dnss4 Ar address; The dns server address to be passed to a peer when requested. .It Ic nbns4 Ar address; The netbios name server address to be passed to a peer when requested. .It Ic dns_suffix Ar quoted; The dns suffix to be passed to a peer when requested. .It Ic dns_list Ar quoted quoted ... ; A list of split dns suffixes to be passed to a peer when requested. A peer can use this list to selectivly forward dns requests to the .Ic dnss4 server when a query matches one of the supplied split dns suffixes. .It Ic banner Ar quoted; The path to a file that contains a login banner to be passed to a peer when requested. .It Ic pfs_group Ar number; The pfs group number to be passed to a peer when requested. .El .El .Ss Peer Section .Bl -tag -width Ds -compact .It Ic peer Ar address [ number ] Ic { Ar statements Ic } Specifies the parameters used to communicate with a given peer by address and optional port number. If the port value is omitted, the default isakmp port number will be used ( 500 ). If an address of 0.0.0.0 is used, the peer section can be used for any remote host. Multiple .Ic peer sections may be defined. .Pp .Bl -tag -width Ds -compact .It Ic contact (initiator | responder | both) ; Specifies the contact type when establishing phase1 negotiations with a peer. If .Ic initiator is used, the daemon will initiate contact but deny contact initiated by the peer. If .Ic responder is used, the daemon will allow contact initiated by the peer but will not initiate contact. If .Ic both is specified, the daemon will initiate contact and allow the peer to initiate contact. .It Ic exchange (main | aggressive) ; Specifies the exchange type to be used for phase1 negotiations with a peer. The default value for this paramater is .Ic main . .It Ic natt_mode (disable | enable | force [ draft | rfc ] ) ; Specifies the NAT Traversal mode to be used for phase1 negotiations with a peer. If .Ic disable is used, natt negotiations will not be attempted. If .Ic enable is used, the daemon will attempt to negotiate and use NAT Traversal when appropriate. If .Ic force is used, the daemon will use NAT Traversal even if the peer does not negotiate support for this feature. When force is used, the .Ic draft or .Ic rfc modifiers can optionally be specified to select the required method with .Ic rfc being the default if omitted. The default value for this parameter is .Ic disable . .It Ic natt_port Ar number ; Specifies the NAT Traversal port number to be used for phase1 negotiations with a peer when acting as an initiator. The default value for this parameter is 4500. .It Ic natt_rate Ar number ; Specifies the number of seconds between sending NAT Traversal keep-alive messages. The default value for this parameter is 15. .It Ic dpd_mode (disable | enable | force) ; Specifies the Dead Peer Detection mode to be used with a peer. If .Ic disable is used, DPD negotiations will not be attempted. If .Ic enable is used, the daemon will attempt to negotiate and use DPD when appropriate. If .Ic force is used, the daemon will use DPD even if the peer does not negotiate support for this feature. The default value for this parameter is .Ic disable . .It Ic dpd_delay Ar number ; Specifies the number of seconds between sending DPD are-you-there messages. The default value for this parameter is 15. .It Ic dpd_retry Ar number ; Specifies the number times a DPD are-you-there message will be retransmitted when no response is received. The default value for this parameter is 5. .It Ic frag_ike_mode (disable | enable | force) ; Specifies the IKE Fragmentation mode to be used with a peer. If .Ic disable is used, IKE Fragmentation negotiations will not be attemted. If .Ic enable is used, the daemon will attempt to negotiate and use IKE Fragmentation when appropriate. If .Ic force is used, the daemon will use IKE Fragmentation even if the peer does not negotiate support for this feature. The default value for this parameter is .Ic disable . .It Ic frag_ike_size Ar number ; Specifies the maximum number of bytes for an IKE Fragment. The default value for this parameter is 520. .It Ic frag_esp_mode (disable | enable) ; Specifies the ESP Fragmentation mode to be used with a peer. If .Ic disable is used, the daemon will create IPsec SAs without the ESP Fragmentation option. If .Ic enable is used, the daemon will create IPsec SAs with the ESP Fragmentation option. The default value for this parameter is .Ic disable . Note, ESP Fragmentation is only valid for IPsec SAs using NAT Traversal. The operating system must also have support for this feature. ( NetBSD Only ) .It Ic frag_esp_size Ar number ; Specifies the maximum number of bytes for an ESP Fragment. The default value for this parameter is 520. .It Ic peerid (local | remote) Ar type ... ; Specifies either the .Ic local identity to be sent to a peer or the .Ic remote identity to be compared with the value recieved from a peer during phase1 negotiations. The valid identity .Ar types are as follows ... .Bl -tag -width Ds -compact .It Ic address Ar [address] ; An IP Address. If the address value is omitted, the network address used during phase1 negotiations is used. .It Ic fqdn Ar quoted ; A Fully Qualified Domain Name string. .It Ic ufqdn Ar quoted ; A User Fully Qualified Domain Name string. .It Ic asn1dn Ar [quoted] ; An ASN.1 Distinguished Name string. If the quoted value is omitted, the daemon will aquire the DN from the subject field contained within the certificate. .El .It Ic authdata Ar type ... ; Specifies the authentication data to use during phase1 negotiations. The valid authentication data .Ar types are as follows ... .Bl -tag -width Ds -compact .It Ic psk Ar quoted ; A Pre Shared Secret. .It Ic ca Ar quoted [quoted]; A path to a OpenSSL PEM or PSK12 file that contains the Remote Certificate Autority. In the case where a PSK12 file is encrypted, the second quoted parameter specifies the file password. .It Ic cert Ar quoted [quoted]; A path to a OpenSSL PEM or PSK12 file that contains the Local Public Certificate. In the case where a PSK12 file is encrypted, the second quoted parameter specifies the file password. .It Ic pkey Ar quoted [quoted]; A path to a OpenSSL PEM or PSK12 file that contains the Local Private Key. In the case where a PSK12 file is encrypted, the second quoted parameter specifies the password. .El .It Ic life_check Ar level ; Specifies the behavior when validating peer lifetime proposal values. The default level is .Ic claim . The valid levels are as follows ... .Bl -tag -width Ds -compact .It Ic obey A responder will always use the initiators value. .It Ic strict A responder will use the initiators value if it is shorter than the responders. A responder will reject the proposal if the initiators value is greater than the responders. .It Ic claim A responder will use the initiators value if it is shorter than the responders. A responder will use its own value if it is shorter than the initiators. In the second case, the responder will send a RESPONDER-LIFETIME notification to the initiator when responding to phase2 proposals. .It Ic exact ; A responder will reject the proposal if the initiators value is not equal to the responders. .El .It Ic xauth_source (local | ldap) Ar [quoted] ; Sepcifies the Extended Authentication source to be used for user authentication post phase1 negotitations. The optional quoted value specifies a group name that can be used to restrict access to only users that are valid members of the group. If .Ic local is used, the peer supplied credentials will be compared to the local account database. If .Ic ldap is used, the peer supplied credentials will be compared to an LDAP account database. The LDAP source configuration is defined in the .Ic xauth_ldap section. The default value for this parameter is .Ic local . .It Ic xconf_source local Ic [(push | pull)]; Sepcifies the Configuration Exchange source to be used when responding to peer configuration requests. If .Ic local is used, the daemon will supply configuration information defined in the .Ic xconf_local section. The default value for this parameter is .Ic local . .It Ic plcy_mode (disable | config | compat) ; Specifies the policy generation mode. When .Ic disable is used, no policy generation is performed. When .Ic config mode is used, policy generation is performed during Configuration Exchange. This allows the daemon to generate polices using the peers private tunnel address. When .Ic compat mode is used, policy generation is performed post phase1 negotiations. This allows the daemon to interoperate with peers that do not support Configuration Exchanges. .It Ic plcy_list { Ar statements Ic } Specifies a list of network groups and parameters that can be used to perform policy generation. If no .Ic plcy_list is defined but .Ic plcy_mode is set to .Ic config or .Ic compat , the daemon operates as if a single .Ic include statement was used that specified a netmap defining all networks. .Bl -tag -width Ds -compact .It Ic (include | exclude) Ar label [quoted] ; Specifies a .Ic netgroup by label for use with policy generation. When .Ic include is used, the daemon will generate appropriate IPsec policies and pass all .Ic netgroup defined networks during the Configuration Exchange if requested. A peer would use this configuration information to selectively tunnel all traffic destined for any one of these networks. If .Ic exlcude is used, the daemon will generate appropriate discard policies and pass all .Ic netgroup defined networks during the Configuration Exchange if requested. A peer would use this configuration information to selectively bypass IPsec processing for all traffic destined to any one of these networks. The optional quoted string specifies a group name that can be used to restrict processing of this netgroup to only users that are valid members of the group. If XAuth is not performed, statements that define a group name are skipped. .El .It Ic proposal Ar type { statements } Specifies a proposal to be used during SA negotiations with a peer. The valid proposal types are as follows ... .Bl -tag -width Ds -compact .Pp .It Ic isakmp An ISAKMP proposal supports the following ... .Bl -tag -width Ds -compact .It Ic auth Ar type ; Define the authentication mechanism for the ISAKMP proposal. The accepted types are .Ic hybrid_xauth_rsa , mutual_xauth_rsa , mutual_xauth_psk , mutual_rsa and .Ic mutual_psk . .It Ic ciph Ar type [number] ; Define the cipher algorithm for this proposal. The optional number specifies the keylength for algorithms that support it. The accepted types are .Ic aes , blowfish , 3des , cast and .Ic des . .It Ic hash Ar type ; Define the hash algorithm for this proposal. The accepted types are .Ic md5 and .Ic sha1 . .It Ic dhgr Ar number ; Define the DH group for this proposal. The accepted values are .Ic 1 , 2 , 5 , 14 , 15, 16, 17, 18 and .Ic 16 . .El .Pp .It Ic ah An AH proposal supports the following ... .Bl -tag -width Ds -compact .It Ic hash Ar type ; Define the hash algorithm for this proposal. The accepted types are .Ic md5 and .Ic sha1 . .It Ic dhgr Ar number ; Define the DH group for this proposal. The accepted values are .Ic 1 , 2 , 5 , 14 , 15, 16, 17, 18 and .Ic 16 . .El .Pp .It Ic esp An ESP proposal supports the following ... .Bl -tag -width Ds -compact .It Ic ciph Ar type [number] ; Define the cipher algorithm for this proposal. The optional number specifies the keylength for algorithms that support it. The accepted types are .Ic aes , blowfish , 3des , cast and .Ic des . .It Ic hmac Ar type ; Define the message authentication algorithm for this proposal. The accepted types are .Ic md5 and .Ic sha1 . .It Ic dhgr Ar number ; Define the DH group for this proposal. The accepted values are .Ic 1 , 2 , 5 , 14 , 15, 16, 17, 18 and .Ic 16 . .El .Pp .It Ic ipcomp An IPCOMP proposal supports the following ... .Bl -tag -width Ds -compact .It Ic comp Ar type ; Define the compression algorithm for this proposal. The accepted types are .Ic deflate and .Ic lzs . .El .El .Pp All proposals types support the following ... .Pp .Bl -tag -width Ds -compact .It Ic life_sec Ar number ; Define the lifetime in seconds for this proposal. .It Ic life_kbs Ar number ; Define the lifetime in kilobytes for this proposal. .El .El .El .Pp .Sh EXAMPLES .Pp This section contains a few iked configuration examples. .Pp The first example shows a configuration that only defines the parameters required to support client connectivity mode with NATT and debug options enabled. .Bd -literal -offset daemon { socket ike 500; socket natt 4500; log_level debug; log_file "/var/log/iked.log"; pcap_decrypt "/var/log/ike-decrypt.pcap"; pcap_encrypt "/var/log/ike-encrypt.pcap"; retry_delay 10; retry_count 2; } .Ed .Pp The second example shows a configuration that supports simple peer to peer negotiations using mutual preshared key authentication. .Bd -literal -offset daemon { socket ike 500; log_level debug; log_file "/var/log/iked.log"; } peer 1.2.3.4 { exchange main; peerid local address; peerid remote address; authdata psk "sharedsecret"; life_check claim; proposal isakmp { auth mutual_psk; life_sec 28800; life_kbs 0; } proposal esp { life_sec 3800; life_kbs 0; } } .Ed .Pp The third example shows a configuration that supports client gateway negotiations using mutual preshared key authentication with xauth, nat traversal, dead peer detection, ike fragmentation and policy generation. The daemon would allow xauth users that are members of the "remote" group to connect to the gateway. Policies would be generated to allow a peer access to the 10.1.1.0/24 and 1.3.3.0/24 networks with the exception of 1.1.1.15/32 which be accessed directly ( not via IPsec ). Peers that use an xauth user account that is a member of the "netadmin" group would have additional policies generated to allow access to the 10.4.4.0/24 network. .Bd -literal -offset daemon { socket ike 500; socket natt 4500; log_level debug; log_file "/var/log/iked.log"; pcap_decrypt "/var/log/ike-decrypt.pcap"; pcap_encrypt "/var/log/ike-encrypt.pcap"; } netgroup allow { 10.1.1.0/24; 10.3.3.0/24; } netgroup deny { 1.1.1.15/32; } netgroup protect { 10.4.4.0/24; } xconf_local { network4 10.2.1.0/24; dnss4 10.1.1.1; nbns4 10.1.1.1; dns_suffix "foo.com"; dns_list "foo.com" "bar.com"; banner "/usr/local/etc/iked.motd"; pfs_group 2; } peer 0.0.0.0 { contact responder; exchange main; natt_mode enable; dpd_mode enable; frag_ike_mode enable; peerid local address; peerid remote address; authdata psk "sharedsecret"; life_check claim; xauth_source local "remote"; xconf_source local; plcy_mode config; plcy_list { include allow; exclude deny; include protect "netadmin"; } proposal isakmp { auth mutual_xauth_psk; ciph 3des; hash md5; dhgr 2; life_sec 28800; life_kbs 0; } proposal esp { life_sec 3800; life_kbs 0; } } .Ed .Sh SEE ALSO .Xr ipsec 4 , .Xr iked 8 , .Xr setkey 8 .Sh HISTORY The .Nm parser was written by Matthew Grooms ( mgrooms@shrew.net ) as part of the Shrew Soft ( http://www.shrew.net ) family of IPsec products. ike-2.2.1+dfsg/source/iked/iked.conf.sample000066400000000000000000000004601223036517100204620ustar00rootroot00000000000000# # sample client iked.conf file # daemon { # bind to ports socket ike 500; socket natt 4500; # log output log_level error; log_file "/var/log/iked.log"; # pcap_decrypt "/var/log/ike-decrypt.pcap"; # pcap_encrypt "/var/log/ike-encrypt.pcap"; # retry settings retry_delay 10; retry_count 2; } ike-2.2.1+dfsg/source/iked/iked.cpp000066400000000000000000000253141223036517100170440ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "iked.h" long _IKED_EXEC::func( void * arg ) { long result = iked_func( arg ); // openssl thread cleanup ERR_remove_state( 0 ); return result; } bool _IKED::rand_bytes( void * buff, long size ) { RAND_pseudo_bytes( ( unsigned char * ) buff, size ); return true; } void _IKED::set_files( char * set_path_conf, const char * set_path_log ) { strcpy_s( path_conf, MAX_PATH, set_path_conf ); strcpy_s( path_log, MAX_PATH, set_path_log ); } void _IKED::loop_ref_inc( const char * name ) { log.txt( LLOG_INFO, "ii : %s process thread begin ...\n", name ); lock_run.lock(); long tempcount = loopcount++; lock_run.unlock(); if( tempcount == 0 ) cond_run.reset(); } void _IKED::loop_ref_dec( const char * name ) { log.txt( LLOG_INFO, "ii : %s process thread exit ...\n", name ); lock_run.lock(); long tempcount = --loopcount; lock_run.unlock(); if( tempcount == 0 ) cond_run.alert(); } _IKED::_IKED() { path_conf[ 0 ] = 0; path_log[ 0 ] = 0; peercount = 0; loopcount = 0; tunnelid = 2; policyid = 1; dnsgrpid = 0; logflags = LOGFLAG_ECHO; retry_count = 2; retry_delay = 5; sock_ike_open = 0; sock_natt_open = 0; rand_bytes( &ident, 2 ); lock_run.name( "run" ); lock_net.name( "net" ); lock_idb.name( "idb" ); cond_run.alert(); cond_idb.alert(); unsigned char xauth[] = VEND_XAUTH; vend_xauth.set( xauth, sizeof( xauth ) ); unsigned char frag[] = VEND_FRAG; vend_frag.set( frag, sizeof( frag ) ); unsigned char dpd1[] = VEND_DPD1; vend_dpd1.set( dpd1, sizeof( dpd1 ) ); unsigned char dpd1_ng[] = VEND_DPD1_NG; vend_dpd1_ng.set( dpd1_ng, sizeof( dpd1_ng ) ); unsigned char hbeat[] = VEND_HBEAT; vend_hbeat.set( hbeat, sizeof( hbeat ) ); unsigned char natt_v00[] = VEND_NATT_V00; vend_natt_v00.set( natt_v00, sizeof( natt_v00 ) ); unsigned char natt_v01[] = VEND_NATT_V01; vend_natt_v01.set( natt_v01, sizeof( natt_v01 ) ); unsigned char natt_v02[] = VEND_NATT_V02; vend_natt_v02.set( natt_v02, sizeof( natt_v02 ) ); unsigned char natt_v03[] = VEND_NATT_V03; vend_natt_v03.set( natt_v03, sizeof( natt_v03 ) ); unsigned char natt_rfc[] = VEND_NATT_RFC; vend_natt_rfc.set( natt_rfc, sizeof( natt_rfc ) ); unsigned char ssoft[] = VEND_SSOFT; vend_ssoft.set( ssoft, sizeof( ssoft ) ); unsigned char kame[] = VEND_KAME; vend_kame.set( kame, sizeof( kame ) ); unsigned char unity[] = VEND_UNITY; vend_unity.set( unity, sizeof( unity ) ); unsigned char netsc[] = VEND_NETSC; vend_netsc.set( netsc, sizeof( netsc ) ); unsigned char zwall[] = VEND_ZWALL; vend_zwall.set( zwall, sizeof( zwall ) ); unsigned char swind[] = VEND_SWIND; vend_swind.set( swind, sizeof( swind ) ); unsigned char chkpt[] = VEND_CHKPT; vend_chkpt.set( chkpt, sizeof( chkpt ) ); unsigned char fwtype[] = UNITY_FWTYPE; unity_fwtype.set( fwtype, sizeof( fwtype ) ); dump_decrypt = false; dump_encrypt = false; conf_fail = false; } _IKED::~_IKED() { // cleanup our object lists idb_list_policy.clean(); idb_list_netgrp.clean(); } long _IKED::init( long setlevel ) { // // initialize ike service interface // if( ikes.init() != IPCERR_OK ) { printf( "Another instance of iked was detected\n" ); return LIBIKE_FAILED; } // // ititialize openssl libcrypto // crypto_init(); // // open our log ( debug and echo ) // log.open( NULL, LLOG_DEBUG, logflags ); // // load our configuration // if( !conf_load( PATH_CONF ) ) return LIBIKE_FAILED; // // open our log ( config settings ) // if( setlevel ) level = setlevel; bool logging = log.open( path_log, level, logflags ); // // output our identity // log.txt( LLOG_NONE, "## : IKE Daemon, ver %d.%d.%d\n" "## : Copyright %i Shrew Soft Inc.\n" "## : This product linked %s\n", CLIENT_VER_MAJ, CLIENT_VER_MIN, CLIENT_VER_BLD, CLIENT_YEAR, SSLeay_version( SSLEAY_VERSION ) ); if( logflags & LOGFLAG_SYSTEM ) log.txt( LLOG_INFO, "ii : opened system log facility\n" ); else { if( !logging ) log.txt( LLOG_ERROR, "!! : failed to open %s\n", path_log ); else log.txt( LLOG_INFO, "ii : opened \'%s\'\n", path_log ); } // // open our packet dump interfaces // if( dump_decrypt ) { if( !pcap_decrypt.open( path_decrypt ) ) log.txt( LLOG_ERROR, "!! : failed to open %s\n", path_decrypt ); else log.txt( LLOG_INFO, "ii : opened \'%s\'\n", path_decrypt ); } if( dump_encrypt ) { if( !pcap_encrypt.open( path_encrypt ) ) log.txt( LLOG_ERROR, "!! : failed to open %s\n", path_encrypt ); else log.txt( LLOG_INFO, "ii : opened \'%s\'\n", path_encrypt ); } // // load our dhcp seed file // #ifdef UNIX bool dhcp_seed_loaded = false; FILE * fp = fopen( path_dhcp, "r" ); if( fp != NULL ) { unsigned int seed[ 6 ]; if( fscanf( fp, "%02x:%02x:%02x:%02x:%x:%02x", &seed[ 0 ], &seed[ 1 ], &seed[ 2 ], &seed[ 3 ], &seed[ 4 ], &seed[ 5 ] ) == 6 ) { dhcp_seed[ 0 ] = ( char ) seed[ 0 ]; dhcp_seed[ 1 ] = ( char ) seed[ 1 ]; dhcp_seed[ 2 ] = ( char ) seed[ 2 ]; dhcp_seed[ 3 ] = ( char ) seed[ 3 ]; dhcp_seed[ 4 ] = ( char ) seed[ 4 ]; dhcp_seed[ 5 ] = ( char ) seed[ 5 ]; dhcp_seed_loaded = true; } fclose( fp ); } if( dhcp_seed_loaded == false ) { FILE * fp = fopen( path_dhcp, "w" ); if( fp != NULL ) { rand_bytes( dhcp_seed, 6 ); unsigned int seed[ 6 ]; seed[ 0 ] = dhcp_seed[ 0 ]; seed[ 1 ] = dhcp_seed[ 1 ]; seed[ 2 ] = dhcp_seed[ 2 ]; seed[ 3 ] = dhcp_seed[ 3 ]; seed[ 4 ] = dhcp_seed[ 4 ]; seed[ 5 ] = dhcp_seed[ 5 ]; if( fprintf( fp, "%02x:%02x:%02x:%02x:%02x:%02x", seed[ 0 ], seed[ 1 ], seed[ 2 ], seed[ 3 ], seed[ 4 ], seed[ 5 ] ) != 18 ) dhcp_seed_loaded = true; else log.txt( LLOG_ERROR, "!! : failed to write dhcp seed to %s\n", path_dhcp ); fclose( fp ); } else log.txt( LLOG_ERROR, "!! : failed to create dhcp seed to %s\n", path_dhcp ); } #endif // // initialize our vnet interface // vnet_init(); // // initialize our socket interface // socket_init(); // // setup natt port on OSX systems // #ifdef __APPLE__ int natt_port = LIBIKE_NATT_PORT; sysctlbyname( "net.inet.ipsec.esp_port", NULL, NULL, &natt_port, sizeof( natt_port ) ); #endif // // default socket initialization // if( !sock_ike_open ) { IKE_SADDR saddr; memset( &saddr, 0, sizeof( saddr ) ); SET_SALEN( &saddr.saddr4, sizeof( sockaddr_in ) ); saddr.saddr4.sin_family = AF_INET; saddr.saddr4.sin_port = htons( LIBIKE_IKE_PORT ); if( socket_create( saddr, false ) != LIBIKE_OK ) { char txtaddr[ 16 ]; text_addr( txtaddr, &saddr, true ); log.txt( LLOG_ERROR, "!! : unable to open ike socket for %s\n", txtaddr ); return LIBIKE_FAILED; } } #ifdef OPT_NATT if( !sock_natt_open ) { IKE_SADDR saddr; memset( &saddr, 0, sizeof( saddr ) ); SET_SALEN( &saddr.saddr4, sizeof( sockaddr_in ) ); saddr.saddr4.sin_family = AF_INET; saddr.saddr4.sin_port = htons( LIBIKE_NATT_PORT ); if( socket_create( saddr, true ) != LIBIKE_OK ) { char txtaddr[ 16 ]; text_addr( txtaddr, &saddr, true ); log.txt( LLOG_ERROR, "!! : unable to open natt socket for %s\n", txtaddr ); return LIBIKE_FAILED; } } #endif return LIBIKE_OK; } void _IKED::loop() { // // start our ike network thread // ith_nwork.exec( this ); // // start our ike pfkey thread // ith_pfkey.exec( this ); // // start our ike client / server thread // ith_ikes.exec( this ); // // enter event timer loop // ith_timer.run(); // // wait for all threads to exit // cond_run.wait( -1 ); // // cleanup // socket_done(); ikes.done(); log.close(); // // cleanup openssl libcrypto // crypto_done(); } long _IKED::halt( bool terminate ) { if( terminate ) { log.txt( LLOG_INFO, "ii : hard halt signal received, shutting down\n" ); // // exit event timer loop // ith_timer.end(); // // remove all top level db objects // idb_list_peer.clean(); cond_idb.wait( -1 ); // // terminate all thread loops // ikes.wakeup(); pfki.wakeup(); socket_wakeup(); } else { log.txt( LLOG_INFO, "ii : soft halt signal received, closing tunnels\n" ); // // remove all top level db objects // idb_list_peer.clean(); cond_idb.wait( -1 ); } return LIBIKE_OK; } ike-2.2.1+dfsg/source/iked/iked.h000066400000000000000000000671311223036517100165140ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #ifndef _IKED_H_ #define _IKED_H_ #ifdef WIN32 # include # include # include # include # include # include # include "libvflt.h" # include "libvnet.h" # include "ipsec.h" #endif #ifdef UNIX # ifdef __linux__ # include # include # include # include # include # include # include # include # else # include # include # include # include # include # include # include # include # ifndef __APPLE__ # include # else # include # include "compat/tun_ioctls.h" # endif # endif # ifdef __FreeBSD__ # include # endif # include "compat/winstring.h" # ifndef SOCKET # define SOCKET int # endif # ifndef INVALID_SOCKET # define INVALID_SOCKET -1 # endif #endif #ifdef OPT_LDAP # include #endif #include "version.h" #include "libip.h" #include "liblog.h" #include "libith.h" #include "libpfk.h" #include "libike.h" #include "libidb.h" #include "crypto.h" #include "ike.h" #include "iked.idb.h" #include "xauth.h" #include "xconf.h" // // Win32 specific // #ifdef WIN32 #define PATH_CONF "SOFTWARE\\ShrewSoft\\vpn" #define SET_SALEN( A, B ) #endif // // Unix specific // #ifdef UNIX #ifndef PATH_CONF #define PATH_CONF "/etc/iked.conf" #endif #ifdef __linux__ #define SET_SALEN( A, B ) #else #define SET_SALEN( A, B ) ((sockaddr*)(A))->sa_len = B #endif #define PATH_DEBUG "/var/log" #define MAX_PATH 1024 namespace yy{ class conf_parser; }; #endif // // IKED constants // // Netscreen-01 299ee8289f40a8973bc78687e2e7226b532c3b76 // Netscreen-02 3a15e1f3cf2a63582e3ac82d1c64cbe3b6d779e7 // Netscreen-03 47d2b126bfcd83489760e2cf8c5d4d5a03497c15 // Netscreen-04 4a4340b543e02b84c88a8b96a8af9ebe77d9accc // Netscreen-05 64405f46f03b7660a23be116a1975058e69e8387 // Netscreen-06 699369228741c6d4ca094c93e242c9de19e7b7c6 // Netscreen-07 8c0dc6cf62a0ef1b5c6eabd1b67ba69866adf16a // Netscreen-08 92d27a9ecb31d99246986d3453d0c3d57a222a61 // Netscreen-09 9b096d9ac3275a7d6fe8b91c583111b09efed1a0 // Netscreen-10 bf03746108d746c904f1f3547de24f78479fed12 // Netscreen-11 c2e80500f4cc5fbf5daaeed3bb59abaeee56c652 // Netscreen-12 c8660a62b03b1b6130bf781608d32a6a8d0fb89f // Netscreen-13 f885da40b1e7a9abd17655ec5bbec0f21f0ed52e // Netscreen-14 2a2bcac19b8e91b426107807e02e7249569d6fd3 // Netscreen-15 166f932d55eb64d8e4df4fd37e2313f0d0fd8451 // Netscreen-16 a35bfd05ca1ac0b3d2f24e9e82bfcbff9c9e52b5 #define VEND_XAUTH { 0x09, 0x00, 0x26, 0x89, 0xDF, 0xD6, 0xB7, 0x12 } #define VEND_FRAG { 0x40, 0x48, 0xb7, 0xd5, 0x6e, 0xbc, 0xe8, 0x85, 0x25, 0xe7, 0xde, 0x7f, 0x00, 0xd6, 0xc2, 0xd3, 0x80, 0x00, 0x00, 0x00 } #define VEND_DPD1 { 0xaf, 0xca, 0xd7, 0x13, 0x68, 0xa1, 0xf1, 0xc9, 0x6b, 0x86, 0x96, 0xfc, 0x77, 0x57, 0x01, 0x00 } #define VEND_DPD1_NG { 0x3b, 0x90, 0x31, 0xdc, 0xe4, 0xfc, 0xf8, 0x8b, 0x48, 0x9a, 0x92, 0x39, 0x63, 0xdd, 0x0c, 0x49 } #define VEND_HBEAT { 0x48, 0x65, 0x61, 0x72, 0x74, 0x42, 0x65, 0x61, 0x74, 0x5f, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x38, 0x6b, 0x01, 0x00 } #define VEND_NATT_V00 { 0x44, 0x85, 0x15, 0x2d, 0x18, 0xb6, 0xbb, 0xcd, 0x0b, 0xe8, 0xa8, 0x46, 0x95, 0x79, 0xdd, 0xcc } #define VEND_NATT_V01 { 0x16, 0xf6, 0xca, 0x16, 0xe4, 0xa4, 0x06, 0x6d, 0x83, 0x82, 0x1a, 0x0f, 0x0a, 0xea, 0xa8, 0x62 } #define VEND_NATT_V02 { 0x90, 0xcb, 0x80, 0x91, 0x3e, 0xbb, 0x69, 0x6e, 0x08, 0x63, 0x81, 0xb5, 0xec, 0x42, 0x7b, 0x1f } #define VEND_NATT_V03 { 0x7d, 0x94, 0x19, 0xa6, 0x53, 0x10, 0xca, 0x6f, 0x2c, 0x17, 0x9d, 0x92, 0x15, 0x52, 0x9d, 0x56 } #define VEND_NATT_RFC { 0x4a, 0x13, 0x1c, 0x81, 0x07, 0x03, 0x58, 0x45, 0x5c, 0x57, 0x28, 0xf2, 0x0e, 0x95, 0x45, 0x2f } #define VEND_SSOFT { 0xf1, 0x4b, 0x94, 0xb7, 0xbf, 0xf1, 0xfe, 0xf0, 0x27, 0x73, 0xb8, 0xc4, 0x9f, 0xed, 0xed, 0x26 } #define VEND_KAME { 0x70, 0x03, 0xcb, 0xc1, 0x09, 0x7d, 0xbe, 0x9c, 0x26, 0x00, 0xba, 0x69, 0x83, 0xbc, 0x8b, 0x35 } #define VEND_UNITY { 0x12, 0xf5, 0xf2, 0x8c, 0x45, 0x71, 0x68, 0xa9, 0x70, 0x2d, 0x9f, 0xe2, 0x74, 0xcc } #define VEND_NETSC { 0x16, 0x6f, 0x93, 0x2d, 0x55, 0xeb, 0x64, 0xd8, 0xe4, 0xdf, 0x4f, 0xd3, 0x7e, 0x23, 0x13, 0xf0, 0xd0, 0xfd, 0x84, 0x51 } #define VEND_ZWALL { 0x62, 0x50, 0x27, 0x74, 0x9d, 0x5a, 0xb9, 0x7f, 0x56, 0x16, 0xc1, 0x60, 0x27, 0x65, 0xcf, 0x48, 0x0a, 0x3b, 0x7d, 0x0b } #define VEND_SWIND { 0x84, 0x04, 0xad, 0xf9, 0xcd, 0xa0, 0x57, 0x60, 0xb2, 0xca, 0x29, 0x2e, 0x4b, 0xff, 0x53, 0x7b } #define VEND_SWALL { 0x40, 0x4B, 0xF4, 0x39, 0x52, 0x2C, 0xA3, 0xF6 } #define VEND_CHKPT { 0xf4, 0xed, 0x19, 0xe0, 0xc1, 0x14, 0xeb, 0x51, 0x6f, 0xaa, 0xac, 0x0e, 0xe3, 0x7d, 0xaf, 0x28, 0x07, 0xb4, 0x38, 0x1f } #define UNITY_FWTYPE { 0x80, 0x01, 0x00, 0x01, 0x80, 0x02, 0x00, 0x01, 0x80, 0x03, 0x00, 0x02 }; #define LIBIKE_IKE_PORT 500 // default isakmp port #define LIBIKE_NATT_PORT 4500 // default nat-t port #define LIBIKE_MAX_TEXTPROT 5 // max text protocol length #define LIBIKE_MAX_TEXTADDR 24 // max text address length #define LIBIKE_MAX_TEXTPORT 6 // max text port length #define LIBIKE_MAX_TEXTP1ID 256 // max text phase1 id length #define LIBIKE_MAX_TEXTP2ID 64 // max text phase2 id length #define LIBIKE_MAX_TEXTSPI 64 // max text phase2 id length #define LIBIKE_MAX_VARID 512 // max variable id length #define LIBIKE_MAX_DHGRP 1024 // max dh group size #define LIBIKE_OK 0 #define LIBIKE_FAILED -1 #define LIBIKE_SOCKET -2 #define LIBIKE_NODATA -3 #define LIBIKE_HOSTNAME -4 #define LIBIKE_HOSTPORT -5 #define LIBIKE_MEMORY -6 #define LIBIKE_ENCODE -7 #define LIBIKE_DECODE -8 #define LTIME_OBEY 1 #define LTIME_CLAIM 2 #define LTIME_STRICT 3 #define LTIME_EXACT 4 #define NAME_INITIATOR 1 #define NAME_EXCHANGE 2 #define NAME_PROTOCOL 3 #define NAME_XFORM_ISAKMP 4 #define NAME_XFORM_AH 5 #define NAME_XFORM_ESP 6 #define NAME_XFORM_IPCOMP 7 #define NAME_PAYLOAD 8 #define NAME_CIPHER 9 #define NAME_MAUTH 10 #define NAME_PAUTH 11 #define NAME_HASH 12 #define NAME_CERT 13 #define NAME_GROUP 14 #define NAME_ENCAP 15 #define NAME_IDENT 16 #define NAME_NOTIFY 17 #define XSTATE_SENT_SA 0x00000001 #define XSTATE_SENT_KE 0x00000002 #define XSTATE_SENT_NO 0x00000004 #define XSTATE_SENT_ID 0x00000008 #define XSTATE_SENT_CT 0x00000010 #define XSTATE_SENT_CR 0x00000020 #define XSTATE_SENT_SI 0x00000040 #define XSTATE_SENT_HA 0x00000080 #define XSTATE_RECV_SA 0x00000100 #define XSTATE_RECV_KE 0x00000200 #define XSTATE_RECV_NO 0x00000400 #define XSTATE_RECV_ID 0x00000800 #define XSTATE_RECV_SI 0x00001000 #define XSTATE_RECV_CT 0x00002000 #define XSTATE_RECV_CR 0x00004000 #define XSTATE_RECV_ND 0x00008000 #define XSTATE_RECV_IDL 0x00010000 #define XSTATE_RECV_IDR 0x00020000 #define XSTATE_RECV_HA 0x00040000 #define XSTATE_RECV_LP 0x00080000 #define XSTATE_SENT_LP 0x00100000 #define CSTATE_RECV_XUSER 0x00000001 #define CSTATE_SENT_XUSER 0x00000002 #define CSTATE_RECV_XPASS 0x00000004 #define CSTATE_SENT_XPASS 0x00000008 #define CSTATE_RECV_XRSLT 0x00000010 #define CSTATE_SENT_XRSLT 0x00000020 #define CSTATE_RECV_XCONF 0x00000040 #define CSTATE_SENT_XCONF 0x00000080 #define CSTATE_RECV_ACK 0x00000100 #define CSTATE_SENT_ACK 0x00000200 #define CSTATE_USE_PASSCODE 0x80000000 #define LSTATE_CHKPROP 0x00000001 // proposal verified #define LSTATE_CHKHASH 0x00000002 // hash verified #define LSTATE_CHKIDS 0x00000004 // identity verified #define LSTATE_GENNATD 0x00000008 // natt discovery generated #define LSTATE_HASKEYS 0x00000010 // keys generated #define LSTATE_CLAIMLT 0x00000020 // claim reponder lifetime #define TSTATE_NATT_FLOAT 0x00000001 #define TSTATE_INITIALIZED 0x00000002 #define TSTATE_VNET_CONFIG 0x00000004 #define TSTATE_VNET_ENABLE 0x00000008 #define TSTATE_POLICY_INIT 0x00000010 #define PFLAG_ROUTED 0x00000001 #define PFLAG_NAILED 0x00000002 // negotiate persistent SAs #define PFLAG_INITIAL 0x00000004 // negotiate an initial SA #define RLEVEL_DAEMON 2 #define FILE_OK 0 #define FILE_PATH 1 #define FILE_FAIL 2 // // IKED main classes and structures // typedef class _IKED_EXEC : public _ITH_EXEC { public: virtual long func( void * arg ); virtual long iked_func( void * arg ) = 0; }IKED_EXEC; typedef class _ITH_IKES : public _IKED_EXEC { virtual long iked_func( void * arg ); }ITH_IKES; typedef class _ITH_IKEC : public _IKED_EXEC { virtual long iked_func( void * arg ); }ITH_IKEC; typedef class _ITH_NWORK : public _IKED_EXEC { virtual long iked_func( void * arg ); }ITH_NWORK; typedef class _ITH_PFKEY : public _IKED_EXEC { virtual long iked_func( void * arg ); }ITH_PFKEY; typedef class _IKED { friend class _ITH_IKES; friend class _ITH_IKEC; friend class _ITH_NWORK; friend class _ITH_PFKEY; friend class _IDB_PEER; friend class _IDB_TUNNEL; friend class _IDB_POLICY; friend class _IDB_XCH; friend class _IDB_PH1; friend class _IDB_PH2; friend class _IDB_CFG; friend class _IDB_INF; friend class _IKED_RC_LIST; friend class _IDB_LIST_IKED; friend class _IDB_LIST_PEER; friend class _IDB_LIST_TUNNEL; friend class _IDB_LIST_POLICY; friend class _IDB_LIST_PH1; friend class _IDB_LIST_PH2; friend class _IDB_LIST_CFG; friend class _ITH_EVENT_TUNDHCP; friend class _ITH_EVENT_TUNDPD; friend class _ITH_EVENT_TUNNATT; friend class _ITH_EVENT_TUNSTATS; friend class _ITH_EVENT_RESEND; friend class _ITH_EVENT_PH1SOFT; friend class _ITH_EVENT_PH1HARD; friend class _ITH_EVENT_PH1DEAD; friend class _ITH_EVENT_PH2SOFT; friend class _ITH_EVENT_PH2HARD; friend class _IKED_XAUTH_SYSTEM; friend class _IKED_XAUTH_LDAP; friend class _IKED_XCONF; friend class _IKED_XCONF_LOCAL; #ifdef UNIX friend class yy::conf_parser; #endif private: char path_ins[ MAX_PATH ]; // install path char path_conf[ MAX_PATH ]; // configuration file char path_log[ MAX_PATH ]; // logfile path char path_decrypt[ MAX_PATH ]; // decrypted pcap path char path_encrypt[ MAX_PATH ]; // encrypted pcap path char path_dhcp[ MAX_PATH ]; // dhcp seed long level; // logging level long logflags; // logging options long peercount; // peer reference count long loopcount; // loop reference count long tunnelid; // next tunnel id short policyid; // next request id long dnsgrpid; // next dns group id long retry_count; // packet retry count long retry_delay; // packet retry delay PFKI pfki; // pfkey interface IKES ikes; // ike service interface IPROUTE iproute; // ip route config interface IPFRAG ipfrag; // ip fragment handling interface ITH_IKES ith_ikes; // server ipc thread ITH_IKEC ith_ikec; // client ipc thread ITH_NWORK ith_nwork; // network thread ITH_PFKEY ith_pfkey; // pfkey thread ITH_TIMER ith_timer; // execution timer short ident; // ip identity ITH_COND cond_idb; // idb null reference condition ITH_COND cond_run; // daemon null reference condition ITH_LOCK lock_run; ITH_LOCK lock_net; ITH_LOCK lock_idb; #ifdef UNIX IDB_LIST list_socket; // socket list int wake_socket[2]; // wakeup socket #endif IDB_LIST idb_list_netgrp; IDB_LIST_PEER idb_list_peer; IDB_LIST_TUNNEL idb_list_tunnel; IDB_LIST_POLICY idb_list_policy; IDB_LIST_PH1 idb_list_ph1; IDB_LIST_PH2 idb_list_ph2; IDB_LIST_CFG idb_list_cfg; long sock_ike_open; long sock_natt_open; bool conf_fail; // known vendor ids BDATA vend_xauth; BDATA vend_frag; BDATA vend_dpd1; BDATA vend_dpd1_ng; BDATA vend_hbeat; BDATA vend_natt_v00; BDATA vend_natt_v01; BDATA vend_natt_v02; BDATA vend_natt_v03; BDATA vend_natt_rfc; BDATA vend_ssoft; BDATA vend_kame; BDATA vend_unity; BDATA vend_netsc; BDATA vend_zwall; BDATA vend_swind; BDATA vend_chkpt; BDATA unity_fwtype; long dump_decrypt; // packet dump decoded traffic long dump_encrypt; // packet dump encoded traffic PCAP_DUMP pcap_decrypt; PCAP_DUMP pcap_encrypt; // xauth and xconf classes _IKED_XAUTH_LOCAL xauth_local; _IKED_XCONF_LOCAL xconf_local; uint8_t dhcp_seed[ 6 ]; // DHCP MAC seed value #ifdef OPT_LDAP IKED_XAUTH_LDAP xauth_ldap; #endif // id name helper functions const char * find_name( long type, long id ); // random helper functions bool rand_bytes( void * buff, long size ); // network helper functions long socket_init(); void socket_done(); long socket_create( IKE_SADDR & saddr, bool natt ); void socket_wakeup(); long socket_lookup_addr( IKE_SADDR & saddr_l, IKE_SADDR & saddr_r ); long socket_lookup_port( IKE_SADDR & saddr_l, bool natt ); #ifdef WIN32 long tunnel_filter_add( IDB_TUNNEL * tunnel, bool natt ); long tunnel_filter_del( IDB_TUNNEL * tunnel ); #endif long header( PACKET_IP & packet, ETH_HEADER & ethhdr ); long recv_ip( PACKET_IP & packet, ETH_HEADER * ethhdr = NULL ); long send_ip( PACKET_IP & packet, ETH_HEADER * ethhdr = NULL ); bool vnet_init(); bool vnet_get( VNET_ADAPTER ** adapter ); bool vnet_rel( VNET_ADAPTER * adapter ); bool client_net_config( IDB_TUNNEL * tunnel ); bool client_net_revert( IDB_TUNNEL * tunnel ); bool client_dns_config( IDB_TUNNEL * tunnel ); bool client_dns_revert( IDB_TUNNEL * tunnel ); #ifdef OPT_DTP bool dnsproxy_check( IKEI * ikei ); bool dnsproxy_setup( IDB_TUNNEL * tunnel ); void dnsproxy_cleanup( IDB_TUNNEL * tunnel ); #endif void text_prot( char * text, int prot ); void text_addr( char * text, in_addr & addr ); void text_mask( char * text, in_addr & addr ); void text_port( char * text, int port ); void text_addr( char * text, sockaddr * saddr, bool port ); void text_addr( char * text, IKE_SADDR * iaddr, bool port ); void text_addr( char * text, PFKI_ADDR * paddr, bool port, bool netmask ); void text_ph1id( char * text, IKE_PH1ID * ph1id ); void text_ph2id( char * text, IKE_PH2ID * ph2id ); // config file loader bool conf_load( const char * path, bool trace = false ); // x.509 certificate helper functions long cert_load( BDATA & cert, char * fpath, bool ca, BDATA & pass ); long cert_load( BDATA & cert, BDATA & input, bool ca, BDATA & pass ); bool cert_desc( BDATA & cert, BDATA & text ); bool cert_subj( BDATA & cert, BDATA & subj ); bool asn1_text( BDATA & asn1, BDATA & text ); bool text_asn1( BDATA & text, BDATA & asn1 ); bool cert_verify( IDB_LIST_CERT & certs, BDATA & ca, BDATA & cert ); long prvkey_rsa_load( BDATA & prvkey, char * fpath, BDATA & pass ); long prvkey_rsa_load( BDATA & prvkey, BDATA & input, BDATA & pass ); bool pubkey_rsa_read( BDATA & cert, BDATA & pubkey ); bool prvkey_rsa_encrypt( BDATA & prvkey, BDATA & hash, BDATA & sign ); bool pubkey_rsa_decrypt( BDATA & pubkey, BDATA & sign, BDATA & hash ); // id helper functions bool gen_ph1id_l( IDB_PH1 * ph1, IKE_PH1ID & ph1id ); bool gen_ph1id_r( IDB_PH1 * ph1, IKE_PH1ID & ph1id ); bool cmp_ph1id( IKE_PH1ID & idt, IKE_PH1ID & ids, bool natt ); bool cmp_ph2id( IKE_PH2ID & idt, IKE_PH2ID & ids, bool exact ); // ike packet handler functions long packet_ike_encap( PACKET_IKE & packet_ike, PACKET_IP & packet_ip, IKE_SADDR & src, IKE_SADDR & dst, long natt ); long packet_ike_send( IDB_PH1 * ph1, IDB_XCH * xch, PACKET_IKE & packet, bool retry ); long packet_ike_xmit( IDB_PH1 * ph1, IDB_XCH * xch, PACKET_IKE & packet, bool retry ); long packet_ike_encrypt( IDB_PH1 * ph1, PACKET_IKE & packet, BDATA * iv ); long packet_ike_decrypt( IDB_PH1 * ph1, PACKET_IKE & packet, BDATA * iv ); // ike exchange handler functions long process_phase1_recv( IDB_PH1 * ph1, PACKET_IKE & packet, unsigned char payload ); long process_phase1_send( IDB_PH1 * ph1 ); long process_phase2_recv( IDB_PH1 * ph1, PACKET_IKE & packet, unsigned char payload ); long process_phase2_send( IDB_PH1 * ph1, IDB_PH2 * ph2 ); long process_config_recv( IDB_PH1 * ph1, PACKET_IKE & packet, unsigned char payload ); long process_config_send( IDB_PH1 * ph1, IDB_CFG * cfg ); long process_inform_recv( IDB_PH1 * ph1, PACKET_IKE & packet, unsigned char payload ); long process_inform_send( IDB_PH1 * ph1, IDB_XCH * inform ); // dhcp over ipsec helper functions long socket_dhcp_create( IDB_TUNNEL * tunnel ); long socket_dhcp_remove( IDB_TUNNEL * tunnel ); long socket_dhcp_send( IDB_TUNNEL * tunnel, PACKET & packet ); long socket_dhcp_recv( IDB_TUNNEL * tunnel, PACKET & packet ); long process_dhcp_send( IDB_TUNNEL * tunnel ); long process_dhcp_recv( IDB_TUNNEL * tunnel ); // policy helper functions bool policy_get_addrs( PFKI_SPINFO * spinfo, IKE_SADDR & src, IKE_SADDR & dst ); bool policy_cmp_prots( PFKI_SPINFO * spinfo1, PFKI_SPINFO * spinfo2 ); bool policy_dhcp_create( IDB_TUNNEL * tunnel ); bool policy_dhcp_remove( IDB_TUNNEL * tunnel ); bool policy_list_create( IDB_TUNNEL * tunnel, bool initiator ); bool policy_list_remove( IDB_TUNNEL * tunnel, bool initiator ); bool policy_create( IDB_TUNNEL * tunnel, u_int16_t type, u_int8_t level, IKE_PH2ID & id1, IKE_PH2ID & id2, bool route ); bool policy_remove( IDB_TUNNEL * tunnel, u_int16_t type, u_int8_t level, IKE_PH2ID & id1, IKE_PH2ID & id2, bool route ); // proposal helper functions long phase1_gen_prop( IDB_PH1 * ph1 ); long phase1_sel_prop( IDB_PH1 * ph1 ); bool phase1_cmp_prop( IKE_PROPOSAL * proposal1, IKE_PROPOSAL * proposal2, bool initiator, long life_check ); long phase2_gen_prop( IDB_PH2 * ph2, IDB_POLICY * policy ); long phase2_sel_prop( IDB_PH2 * ph2 ); bool phase2_cmp_prop( IKE_PROPOSAL * proposal1, IKE_PROPOSAL * proposal2, bool initiator, long life_check ); // phase1 exchange helper functions long phase1_gen_keys( IDB_PH1 * ph1 ); long phase1_gen_hash_i( IDB_PH1 * ph1, BDATA & hash ); long phase1_gen_hash_r( IDB_PH1 * ph1, BDATA & hash ); bool phase1_chk_port( IDB_PH1 * ph1, IKE_SADDR * saddr_r, IKE_SADDR * saddr_l ); long phase1_add_vend( IDB_PH1 * ph1, PACKET_IKE & packet, uint8_t next ); long phase1_chk_vend( IDB_PH1 * ph1, BDATA & vend ); long phase1_chk_hash( IDB_PH1 * ph1 ); long phase1_chk_sign( IDB_PH1 * ph1 ); long phase1_gen_natd( IDB_PH1 * ph1 ); bool phase1_add_natd( IDB_PH1 * ph1, PACKET_IKE & packet, uint8_t next ); bool phase1_chk_natd( IDB_PH1 * ph1 ); long phase1_chk_idr( IDB_PH1 * ph1 ); // phase2 exchange helper functions long phase2_gen_hash_i( IDB_PH1 * ph1, IDB_PH2 * ph2, BDATA & hash ); long phase2_gen_hash_r( IDB_PH1 * ph1, IDB_PH2 * ph2, BDATA & hash ); long phase2_gen_hash_p( IDB_PH1 * ph1, IDB_PH2 * ph2, BDATA & hash ); long phase2_chk_hash_i( IDB_PH1 * ph1, IDB_PH2 * ph2 ); long phase2_chk_hash_r( IDB_PH1 * ph1, IDB_PH2 * ph2 ); long phase2_chk_hash_p( IDB_PH1 * ph1, IDB_PH2 * ph2 ); long phase2_chk_params( IDB_PH1 * ph1, IDB_PH2 * ph2, PACKET_IKE & packet ); long phase2_gen_keys( IDB_PH1 * ph1, IDB_PH2 * ph2 ); long phase2_gen_keys( IDB_PH1 * ph1, IDB_PH2 * ph2, long dir, IKE_PROPOSAL * proposal, BDATA & shared ); // config exchange helper functions bool config_client_xauth_recv( IDB_CFG * cfg, IDB_PH1 * ph1 ); bool config_client_xauth_send( IDB_CFG * cfg, IDB_PH1 * ph1 ); bool config_client_xconf_pull_recv( IDB_CFG * cfg, IDB_PH1 * ph1 ); bool config_client_xconf_pull_send( IDB_CFG * cfg, IDB_PH1 * ph1 ); bool config_client_xconf_push_recv( IDB_CFG * cfg, IDB_PH1 * ph1 ); bool config_client_xconf_push_send( IDB_CFG * cfg, IDB_PH1 * ph1 ); bool config_server_xauth_recv( IDB_CFG * cfg, IDB_PH1 * ph1 ); bool config_server_xauth_send( IDB_CFG * cfg, IDB_PH1 * ph1 ); bool config_server_xconf_pull_recv( IDB_CFG * cfg, IDB_PH1 * ph1 ); bool config_server_xconf_pull_send( IDB_CFG * cfg, IDB_PH1 * ph1 ); bool config_server_xconf_push_recv( IDB_CFG * cfg, IDB_PH1 * ph1 ); bool config_server_xconf_push_send( IDB_CFG * cfg, IDB_PH1 * ph1 ); long config_xconf_set( IDB_CFG * cfg, long setbits, long setmask, VENDOPTS vendopts ); long config_xconf_get( IDB_CFG * cfg, long & getbits, long getmask, VENDOPTS vendopts ); long config_chk_hash( IDB_PH1 * ph1, IDB_CFG * cfg, unsigned long msgid ); long config_message_send( IDB_PH1 * ph1, IDB_CFG * cfg ); // informational exchange helper functions long inform_get_spi( char * text, IDB_PH1 * ph1, IKE_NOTIFY * notify ); long inform_chk_hash( IDB_PH1 * ph1, IDB_XCH * inform ); long inform_gen_hash( IDB_PH1 * ph1, IDB_XCH * inform ); long inform_chk_notify( IDB_PH1 * ph1, IKE_NOTIFY * notify, bool secure ); long inform_chk_delete( IDB_PH1 * ph1, IKE_NOTIFY * notify, bool secure ); long inform_new_notify( IDB_PH1 * ph1, IDB_PH2 * ph2, unsigned short code, BDATA * data = NULL ); long inform_new_delete( IDB_PH1 * ph1, IDB_PH2 * ph2 ); long inform_gen_iv( IDB_PH1 * ph1, unsigned long msgid, BDATA & iv ); // // isakmp payload handler functions // long payload_add_frag( PACKET_IKE & packet, unsigned char & index, unsigned char * data, size_t & size, size_t max ); long payload_get_frag( PACKET_IKE & packet, IDB_PH1 * ph1, bool & complete ); long payload_add_attr( PACKET_IKE & packet, IKE_ATTR & attrib ); long payload_get_attr( PACKET_IKE & packet, IKE_ATTR & attrib ); long payload_add_sa( PACKET_IKE & packet, IDB_LIST_PROPOSAL & plist, uint8_t next ); long payload_get_sa( PACKET_IKE & packet, IDB_LIST_PROPOSAL & plist ); long payload_add_xform( PACKET_IKE & packet, IKE_PROPOSAL * proposal, uint8_t next ); long payload_get_xform( PACKET_IKE & packet, IKE_PROPOSAL * proposal ); long payload_add_kex( PACKET_IKE & packet, BDATA & gx, uint8_t next ); long payload_get_kex( PACKET_IKE & packet, BDATA & gx ); long payload_add_nonce( PACKET_IKE & packet, BDATA & nonce, uint8_t next ); long payload_get_nonce( PACKET_IKE & packet, BDATA & nonce ); long payload_add_ph1id( PACKET_IKE & packet, IKE_PH1ID & ph1id, uint8_t next ); long payload_get_ph1id( PACKET_IKE & packet, IKE_PH1ID & ph1id ); long payload_add_ph2id( PACKET_IKE & packet, IKE_PH2ID & ph2id, uint8_t next ); long payload_get_ph2id( PACKET_IKE & packet, IKE_PH2ID & ph2id ); long payload_add_hash( PACKET_IKE & packet, BDATA & hash, uint8_t next ); long payload_get_hash( PACKET_IKE & packet, BDATA & hash, long size ); long payload_add_cert( PACKET_IKE & packet, uint8_t type, BDATA & cert, uint8_t next ); long payload_get_cert( PACKET_IKE & packet, uint8_t & type, BDATA & cert ); long payload_add_creq( PACKET_IKE & packet, uint8_t type, uint8_t next ); long payload_get_creq( PACKET_IKE & packet, uint8_t & type, BDATA & dn ); long payload_add_sign( PACKET_IKE & packet, BDATA & sign, uint8_t next ); long payload_get_sign( PACKET_IKE & packet, BDATA & sign ); long payload_add_vend( PACKET_IKE & packet, BDATA & vend, uint8_t next ); long payload_get_vend( PACKET_IKE & packet, BDATA & vend ); long payload_add_cfglist( PACKET_IKE & packet, IDB_CFG * cfg, uint8_t next ); long payload_get_cfglist( PACKET_IKE & packet, IDB_CFG * cfg ); long payload_add_natd( PACKET_IKE & packet, BDATA & natd, uint8_t next ); long payload_get_natd( PACKET_IKE & packet, BDATA & natd, long size ); long payload_add_notify( PACKET_IKE & packet, IKE_NOTIFY * notify, uint8_t next ); long payload_get_notify( PACKET_IKE & packet, IKE_NOTIFY * notify ); long payload_add_delete( PACKET_IKE & packet, IKE_NOTIFY * notify, uint8_t next ); long payload_get_delete( PACKET_IKE & packet, IKE_NOTIFY * notify ); // // main ike process handlers // long process_ike_send(); long process_ike_recv( PACKET_IKE & packet, IKE_SADDR & saddr_src, IKE_SADDR & saddr_dst ); // // pfkey process handlers // bool paddr_ph2id( PFKI_ADDR & paddr, IKE_PH2ID & ph2id ); bool ph2id_paddr( IKE_PH2ID & ph2id, PFKI_ADDR & paddr ); long pfkey_init_phase2( bool nail, u_int16_t plcytype, u_int32_t plcyid, u_int32_t seq ); long pfkey_recv_spadd( PFKI_MSG & msg ); long pfkey_recv_spnew( PFKI_MSG & msg ); long pfkey_recv_acquire( PFKI_MSG & msg ); long pfkey_recv_getspi( PFKI_MSG & msg ); long pfkey_recv_flush( PFKI_MSG & msg ); long pfkey_recv_spdel( PFKI_MSG & msg ); long pfkey_recv_spflush( PFKI_MSG & msg ); long pfkey_send_getspi( IDB_POLICY * policy, IDB_PH2 * ph2 ); long pfkey_send_update( IDB_PH2 * ph2, IKE_PROPOSAL * proposal, BDATA & ekey, BDATA & akey, long dir ); long pfkey_send_delete( IDB_PH2 * ph2 ); long pfkey_send_spadd( PFKI_SPINFO * spinfo ); long pfkey_send_spdel( PFKI_SPINFO * spinfo ); // // execution thread loops // void loop_ref_inc( const char * name ); void loop_ref_dec( const char * name ); long loop_ipc_server(); long loop_ipc_client( IKEI * ikei ); long loop_ike_nwork(); long loop_ike_pfkey(); public: _IKED(); ~_IKED(); LOG log; // generic log object void set_files( char * set_path_conf, const char * set_path_log ); long init( long setlevel ); long halt( bool terminate ); void loop(); }IKED; // // global iked object // extern IKED iked; // // generic utility classes and functions // bool cmp_ikeaddr( IKE_SADDR & addr1, IKE_SADDR & addr2, bool port ); bool has_sockaddr( sockaddr * saddr1 ); bool cmp_sockaddr( sockaddr & saddr1, sockaddr & saddr2, bool port ); bool cpy_sockaddr( sockaddr & saddr1, sockaddr & saddr2, bool port ); bool get_sockport( sockaddr & saddr, u_int16_t & port ); bool set_sockport( sockaddr & saddr, u_int16_t port ); #endif ike-2.2.1+dfsg/source/iked/iked.idb.h000066400000000000000000000470331223036517100172500ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #ifndef _IKE_IDB_H_ #define _IKE_IDB_H_ #ifdef OPT_DTP # include "libdtp.h" #endif //============================================================================== // general classes //============================================================================== typedef class _PACKET_IKE : public _PACKET { protected: PLD_DATA pld_stack[ 8 ]; long pld_depth; IKE_HEADER header; public: unsigned char notify; _PACKET_IKE(); ~_PACKET_IKE(); void reset(); void set_msgid( uint32_t msgid ); uint32_t get_msgid(); bool add_payload( bool encap, uint8_t next ); bool get_payload( bool encap, uint8_t & next ); void end_payload( bool decap, bool write = true ); size_t get_payload_left(); bool write( IKE_COOKIES & cookies, uint8_t payload, uint8_t exchange, uint8_t flags ); bool read( IKE_COOKIES & cookies, uint8_t & payload, uint8_t & exchange, uint8_t & flags ); bool done(); }PACKET_IKE; #ifdef UNIX typedef struct _SOCK_INFO : public IDB_ENTRY { int sock; IKE_SADDR saddr; bool natt; }SOCK_INFO; typedef struct _VNET_ADAPTER { int fn; char name[ IFNAMSIZ ]; }VNET_ADAPTER; #endif //============================================================================== // basic data list // typedef class _IDB_ENTRY_BDATA : public IDB_ENTRY, public BDATA { }IDB_ENTRY_BDATA; typedef class _IDB_LIST_BDATA : public IDB_LIST { public: BDATA name; virtual ~_IDB_LIST_BDATA(); bool add( BDATA & bdata ); bool get( BDATA & bdata, long index ); }IDB_LIST_BDATA; //============================================================================== // ike proposal list // typedef class _IDB_ENTRY_PROPOSAL : public IDB_ENTRY, public IKE_PROPOSAL { public: bool pnext; }IDB_ENTRY_PROPOSAL; typedef class _IDB_LIST_PROPOSAL : public IDB_LIST { public: virtual ~_IDB_LIST_PROPOSAL(); bool add( IKE_PROPOSAL * proposal, bool pnext ); bool get( IKE_PROPOSAL ** proposal, long pindex, uint8_t proto = 0 ); bool nextb( long & bindex, long & pindex, long & pcount ); bool nextp( IKE_PROPOSAL ** proposal, long & pindex, long & tindex, long & tcount ); bool nextt( IKE_PROPOSAL ** proposal, long & tindex ); }IDB_LIST_PROPOSAL; //============================================================================== // ike notification list // typedef class _IDB_ENTRY_NOTIFY : public IDB_ENTRY, public IKE_NOTIFY { }IDB_ENTRY_NOTIFY; typedef class _IDB_LIST_NOTIFY : public IDB_LIST { public: virtual ~_IDB_LIST_NOTIFY(); bool add( IKE_NOTIFY & notify ); bool get( IKE_NOTIFY & notify, long index ); }IDB_LIST_NOTIFY; //============================================================================== // certificate list // typedef class _IDB_ENTRY_CERT : public IDB_ENTRY { public: uint8_t type; BDATA data; }IDB_ENTRY_CERT; typedef class _IDB_LIST_CERT : public IDB_LIST { public: virtual ~_IDB_LIST_CERT(); bool add( uint8_t & type, BDATA & data ); bool get( uint8_t & type, BDATA & data, long index ); }IDB_LIST_CERT; //============================================================================== // phase2 ID list // typedef class _IDB_ENTRY_PH2ID : public IDB_ENTRY, public IKE_PH2ID { }IDB_ENTRY_PH2ID; typedef class _IDB_LIST_PH2ID : public IDB_LIST, public IDB_ENTRY { public: BDATA name; virtual ~_IDB_LIST_PH2ID(); bool add( IKE_PH2ID & ph2id ); bool get( IKE_PH2ID & ph2id, long index ); }IDB_LIST_PH2ID; //============================================================================== // network map list ( list of phase2 ID lists ) // typedef class _IDB_ENTRY_NETMAP : public IDB_ENTRY { public: IDB_LIST_PH2ID * idlist; long mode; BDATA group; }IDB_ENTRY_NETMAP; typedef class _IDB_LIST_NETMAP : public IDB_LIST { public: BDATA name; virtual ~_IDB_LIST_NETMAP(); bool add( IDB_LIST_PH2ID * idlist, long mode, BDATA * group ); bool del( IDB_ENTRY_NETMAP * netmap ); bool get( IDB_ENTRY_NETMAP ** netmap, long index ); }IDB_LIST_NETMAP; //============================================================================== // domain name list // typedef IDB_ENTRY_BDATA IDB_ENTRY_DOMAIN; typedef IDB_LIST_BDATA IDB_LIST_DOMAIN ; //============================================================================== // reference counted IDB derived classes //============================================================================== enum XCH_STATUS { XCH_STATUS_ANY, XCH_STATUS_PENDING, XCH_STATUS_LARVAL, XCH_STATUS_MATURE, XCH_STATUS_EXPIRING, XCH_STATUS_EXPIRED, XCH_STATUS_DEAD }; enum XCH_ERRORCODE { XCH_NORMAL, XCH_FAILED_CLIENT, XCH_FAILED_NETWORK, XCH_FAILED_ADAPTER, XCH_FAILED_TIMEOUT, XCH_FAILED_PENDING, XCH_FAILED_EXPIRED, XCH_FAILED_FLUSHED, XCH_FAILED_USERREQ, XCH_FAILED_MSG_FORMAT, XCH_FAILED_MSG_CRYPTO, XCH_FAILED_MSG_AUTH, XCH_FAILED_USER_AUTH, XCH_FAILED_PEER_AUTH, XCH_FAILED_PEER_DEAD, XCH_FAILED_PEER_DELETE, XCH_FAILED_IKECONFIG, XCH_FAILED_DHCPCONFIG }; typedef struct _VENDOPTS { union { struct { unsigned long xauth :1; unsigned long frag :1; unsigned long dpdv1 :1; unsigned long hbeat :1; unsigned long natt :1; unsigned long ssoft :1; unsigned long kame :1; unsigned long unity :1; unsigned long netsc :1; unsigned long zwall :1; unsigned long swind :1; unsigned long swall :1; unsigned long chkpt :1; }flag; unsigned long flags; }; }VENDOPTS; typedef class _IKED_XAUTH IKED_XAUTH; typedef class _IKED_XCONF IKED_XCONF; typedef class _IDB_TUNNEL IDB_TUNNEL; typedef class _IDB_XCH IDB_XCH; typedef class _IDB_PH1 IDB_PH1; typedef class _IDB_PH2 IDB_PH2; typedef class _IDB_CFG IDB_CFG; //============================================================================== // tunnel event classes // typedef class _ITH_EVENT_TUNDHCP : public ITH_EVENT { public: IDB_TUNNEL * tunnel; time_t lease; time_t renew; long retry; bool func(); }ITH_EVENT_TUNDHCP; typedef class _ITH_EVENT_TUNDPD : public ITH_EVENT { public: IDB_TUNNEL * tunnel; uint32_t sequence; uint32_t attempt; void next(); bool func(); }ITH_EVENT_TUNDPD; typedef class _ITH_EVENT_TUNNATT : public ITH_EVENT { public: IDB_TUNNEL * tunnel; bool func(); }ITH_EVENT_TUNNATT; typedef class _ITH_EVENT_TUNSTATS : public ITH_EVENT { public: IDB_TUNNEL * tunnel; bool func(); }ITH_EVENT_TUNSTATS; //============================================================================== // exchange event classes // typedef class _ITH_EVENT_RESEND : public ITH_EVENT, public IPQUEUE { public: IDB_XCH * xch; IPQUEUE ipqueue; long attempt; bool func(); }ITH_EVENT_RESEND; //============================================================================== // phase1 event classes // typedef class _ITH_EVENT_PH1SOFT : public ITH_EVENT { public: IDB_PH1 * ph1; bool func(); }ITH_EVENT_PH1SOFT; typedef class _ITH_EVENT_PH1HARD : public ITH_EVENT { public: IDB_PH1 * ph1; bool func(); }ITH_EVENT_PH1HARD; typedef class _ITH_EVENT_PH1DEAD : public ITH_EVENT { public: IDB_PH1 * ph1; bool func(); }ITH_EVENT_PH1DEAD; //============================================================================== // phase2 event classes // typedef class _ITH_EVENT_PH2SOFT : public ITH_EVENT { public: IDB_PH2 * ph2; long diff; bool func(); }ITH_EVENT_PH2SOFT; typedef class _ITH_EVENT_PH2HARD : public ITH_EVENT { public: IDB_PH2 * ph2; bool func(); }ITH_EVENT_PH2HARD; //============================================================================== // ike internal data classes // class _IKED_RC_LIST; #define ENTRY_FLAG_DEAD 1 #define ENTRY_FLAG_IMMEDIATE 2 #define ENTRY_FLAG_ENDCALLED 4 typedef class _IKED_RC_ENTRY : public IDB_ENTRY { protected: long idb_flags; long idb_refcount; inline long chkflags( long flags ) { return ( idb_flags & flags ); } inline long setflags( long flags ) { return idb_flags |= flags; } inline long clrflags( long flags ) { return idb_flags &= ~flags; } void callend(); virtual void beg() = 0; virtual void end() = 0; public: _IKED_RC_ENTRY(); virtual ~_IKED_RC_ENTRY(); virtual const char * name() = 0; virtual _IKED_RC_LIST * list() = 0; bool add( bool lock ); void inc( bool lock ); bool dec( bool lock, bool setdel = false ); }IKED_RC_ENTRY; typedef class _IKED_RC_LIST : public IDB_LIST { public: _IKED_RC_LIST(); virtual ~_IKED_RC_LIST(); virtual void clean(); bool lock(); bool unlock(); }IKED_RC_LIST; typedef class _IDB_PEER : public IKED_RC_ENTRY, public IKE_PEER { private: virtual void beg(); virtual void end(); public: BDATA iddata_l; BDATA iddata_r; BDATA cert_l; BDATA cert_r; BDATA cert_k; BDATA psk; BDATA xauth_group; IKED_XAUTH * xauth_source; IKED_XCONF * xconf_source; IDB_LIST_PROPOSAL proposals; IDB_LIST_NETMAP netmaps; virtual const char * name(); virtual IKED_RC_LIST * list(); _IDB_PEER( IKE_PEER * set_peer ); virtual ~_IDB_PEER(); }IDB_PEER; typedef class _IDB_LIST_PEER : public IKED_RC_LIST { public: IDB_PEER * get( int index ); bool find( bool lock, IDB_PEER ** peer, IKE_SADDR * saddr ); }IDB_LIST_PEER; typedef class _IDB_TUNNEL : public IKED_RC_ENTRY { public: long tunnelid; long tstate; long lstate; long natt_version; bool suspended; IDB_PEER * peer; IKEI * ikei; #ifdef OPT_DTP DTPI * dtpi; #endif VNET_ADAPTER * adapter; IKE_SADDR saddr_l; IKE_SADDR saddr_r; // // FIXME : move client stuff into class // IKEI_STATS stats; IKE_XAUTH xauth; IKE_XCONF xconf; IDB_LIST_DOMAIN domains; BDATA banner; XCH_ERRORCODE close; #ifdef WIN32 IKE_NSCFG nscfg; #endif bool force_all; IDB_LIST_PH2ID idlist_incl; IDB_LIST_PH2ID idlist_excl; // // FIXME : move DHCP stuff into class // uint32_t dhcp_xid; uint8_t dhcp_hwtype; uint8_t dhcp_hwaddr[ 6 ]; SOCKET dhcp_sock; ITH_EVENT_TUNDHCP event_dhcp; ITH_EVENT_TUNDPD event_dpd; ITH_EVENT_TUNNATT event_natt; ITH_EVENT_TUNSTATS event_stats; virtual const char * name(); virtual IKED_RC_LIST * list(); virtual void beg(); virtual void end(); _IDB_TUNNEL( IDB_PEER * set_peer, IKE_XCONF * set_xconf, IKE_SADDR * set_saddr_l, IKE_SADDR * set_saddr_r ); virtual ~_IDB_TUNNEL(); }IDB_TUNNEL; typedef class _IDB_LIST_TUNNEL : public IKED_RC_LIST { public: IDB_TUNNEL * get( int index ); bool find( bool lock, IDB_TUNNEL ** tunnel, long * tunnelid, IKE_SADDR * saddr, bool port, bool suspended ); }IDB_LIST_TUNNEL; typedef class _IDB_POLICY : public IKED_RC_ENTRY, public PFKI_SPINFO { public: IPROUTE_ENTRY route_entry; long flags; virtual const char * name(); virtual IKED_RC_LIST * list(); virtual void beg(); virtual void end(); _IDB_POLICY( PFKI_SPINFO * spinfo ); virtual ~_IDB_POLICY(); }IDB_POLICY; typedef class _IDB_LIST_POLICY : public IKED_RC_LIST { public: IDB_POLICY * get( int index ); bool find( bool lock, IDB_POLICY ** policy, long dir, u_int16_t type, u_int32_t * seq, u_int32_t * plcyid, IKE_SADDR * src, IKE_SADDR * dst, IKE_PH2ID * ids, IKE_PH2ID * idd ); void flush(); }IDB_LIST_POLICY; //============================================================================== // ike generic exchange handle class // typedef class _IDB_XCH : public IKED_RC_ENTRY { public: IDB_TUNNEL * tunnel; ITH_LOCK lock; XCH_STATUS xch_status; XCH_ERRORCODE xch_errorcode; uint16_t xch_notifycode; bool initiator; unsigned char exchange; uint32_t msgid; long lstate; long xstate; BDATA hash_l; BDATA hash_r; BDATA hda; // hash data accumulator BDATA iv; IDB_LIST_NOTIFY notifications; ITH_EVENT_RESEND event_resend; _IDB_XCH(); virtual ~_IDB_XCH(); XCH_STATUS status(); XCH_STATUS status( XCH_STATUS status, XCH_ERRORCODE errorcode, uint16_t notifycode ); void new_msgid(); bool new_msgiv( IDB_PH1 * ph1 ); bool resend(); bool resend_queue( PACKET_IP & packet ); void resend_purge(); bool resend_sched( bool lock ); void resend_clear( bool lock, bool purge ); }IDB_XCH; //============================================================================== // ike generic sa exchange handle class // typedef class _IDB_XCH_SA : public IDB_XCH { public: DH * dh; long dh_size; BDATA xl; BDATA xr; BDATA nonce_l; BDATA nonce_r; IDB_LIST_PROPOSAL plist_l; IDB_LIST_PROPOSAL plist_r; _IDB_XCH_SA(); virtual ~_IDB_XCH_SA(); }IDB_XCH_SA; //============================================================================== // ike phase1 exchange handle class // typedef class _IDB_PH1 : public IDB_XCH_SA { virtual void beg(); virtual void end(); public: const EVP_CIPHER * evp_cipher; const EVP_MD * evp_hash; long hash_size; IKE_COOKIES cookies; IKE_PH1ID ph1id_l; IKE_PH1ID ph1id_r; VENDOPTS vendopts_l; VENDOPTS vendopts_r; long natt_version; // version negotiated uint8_t natt_pldtype; // payload identifier uint16_t auth_id; // selected authentication type IDB_LIST frags; BDATA key; BDATA idi; BDATA idr; IDB_LIST_BDATA natd_hash_l; IDB_LIST_BDATA natd_hash_r; IDB_LIST_CERT creqs_r; IDB_LIST_CERT certs_r; BDATA sign_r; BDATA skeyid; BDATA skeyid_d; BDATA skeyid_a; BDATA skeyid_e; ITH_EVENT_PH1SOFT event_soft; ITH_EVENT_PH1HARD event_hard; ITH_EVENT_PH1DEAD event_dead; // sub class functions virtual const char * name(); virtual IKED_RC_LIST * list(); // class functions _IDB_PH1( IDB_TUNNEL * set_tunnel, bool set_initiator, IKE_COOKIES * set_cookies ); virtual ~_IDB_PH1(); bool setup_dhgrp( IKE_PROPOSAL * proposal ); bool setup_xform( IKE_PROPOSAL * proposal ); void clean(); // // FIXME : fragments should be IDB list // bool frag_add( unsigned char * data, unsigned long size, long index, bool last ); bool frag_get( PACKET_IKE & packet ); }IDB_PH1; typedef class _IDB_LIST_PH1 : public IKED_RC_LIST { public: IDB_PH1 * get( int index ); bool find( bool lock, IDB_PH1 ** ph1, IDB_TUNNEL * tunnel, XCH_STATUS min, XCH_STATUS max, IKE_COOKIES * cookies ); }IDB_LIST_PH1; //============================================================================== // ike phase2 exchange handle class // typedef class _IDB_PH2 : public IDB_XCH_SA { public: IKE_COOKIES cookies; uint32_t seqid_in; uint32_t seqid_out; uint32_t plcyid_in; uint32_t plcyid_out; bool nailed; long spicount; long dhgr_id; IKE_PH2ID ph2id_ls; IKE_PH2ID ph2id_ld; IKE_PH2ID ph2id_rs; IKE_PH2ID ph2id_rd; ITH_EVENT_PH2SOFT event_soft; ITH_EVENT_PH2HARD event_hard; // sub class functions virtual const char * name(); virtual IKED_RC_LIST * list(); virtual void beg(); virtual void end(); // class functions _IDB_PH2( IDB_TUNNEL * set_tunnel, bool set_initiator, uint32_t set_msgid, uint32_t set_seqid_in ); virtual ~_IDB_PH2(); bool setup_dhgrp(); bool setup_xform(); void clean(); }IDB_PH2; typedef class _IDB_LIST_PH2 : public IKED_RC_LIST { public: IDB_PH2 * get( int index ); bool find( bool lock, IDB_PH2 ** ph2, IDB_TUNNEL * tunnel, XCH_STATUS min, XCH_STATUS max, u_int32_t * seqid, uint32_t * msgid, IKE_SPI * spi_l, IKE_SPI * spi_r ); void flush(); }IDB_LIST_PH2; //============================================================================== // ike configuraion exchange handle class // typedef class _IDB_CFG : public IDB_XCH { protected: IDB_LIST attrs; public: // this should never be accessed // directly, only for comparison IDB_PH1 * ph1ref; // sub class functions virtual const char * name(); virtual IKED_RC_LIST * list(); virtual void beg(); virtual void end(); // class functions _IDB_CFG( IDB_PH1 * set_ph1ref, bool set_initiator ); virtual ~_IDB_CFG(); BDATA hash; uint8_t mtype; uint16_t ident; // // FIXME : attributes should be IDB list // IKE_ATTR * attr_get( long index ); bool attr_has( unsigned short atype ); bool attr_add_b( unsigned short atype, unsigned short adata ); bool attr_add_v( unsigned short atype, const void * vdata, size_t size ); long attr_count(); // get attribute count void attr_reset(); // reset attribute list bool setup(); void clean(); }IDB_CFG; typedef class _IDB_LIST_CFG : public IKED_RC_LIST { public: IDB_CFG * get( int index ); bool find( bool lock, IDB_CFG ** cfg, IDB_PH1 * ph1 ); }IDB_LIST_CFG; //============================================================================== // ike informational exchange handle class // typedef class _IDB_INF : public IDB_XCH { public: // sub class functions virtual const char * name(); virtual IKED_RC_LIST * list(); virtual void beg(); virtual void end(); // class functions _IDB_INF(); virtual ~_IDB_INF(); }IDB_INF; typedef IKED_RC_LIST IDB_LIST_INF; #endif /// _IKE_IDB_H_ ike-2.2.1+dfsg/source/iked/main.cpp000066400000000000000000000264211223036517100170540ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "iked.h" IKED iked; #ifdef WIN32 // // win32 service specific section // #define SERVICE_NAME "iked" #define SERVICE_DESC "ShrewSoft IKE Daemon" #define INSTALL_HKEY "SOFTWARE\\ShrewSoft\\vpn" SERVICE_STATUS_HANDLE service_handle; SERVICE_STATUS service_status; void service_add( char * path ) { char prog[ MAX_PATH ]; sprintf_s( prog, MAX_PATH, "%s -service", path ); SC_HANDLE hmngr = NULL; SC_HANDLE hsrvc = NULL; hmngr = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); if( hmngr == NULL ) { printf( "!! : unable to open service manager\n" ); exit( 1 ); } hsrvc = CreateService( hmngr, SERVICE_NAME, SERVICE_DESC, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, prog, NULL, NULL, NULL, NULL, NULL ); if( hsrvc != NULL ) printf( "ii : service has been registered\n" ); else printf( "!! : unable to register service\n" ); } void service_del( char * path ) { SC_HANDLE hmngr = NULL; SC_HANDLE hsrvc = NULL; hmngr = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); if( hmngr == NULL ) { printf( "!! : unable to open service manager\n" ); exit( 1 ); } hsrvc = OpenService( hmngr, SERVICE_NAME, SERVICE_ALL_ACCESS ); if( hmngr == NULL ) { printf( "!! : unable to open service\n" ); exit( 1 ); } if( DeleteService( hsrvc ) ) printf( "ii : service has been deregistered\n" ); else printf( "!! : unable to deregister service\n" ); } DWORD __stdcall service_ctrl( DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext ) { switch( dwControl ) { case SERVICE_CONTROL_STOP: // // stop daemon operation // iked.halt( true ); break; case SERVICE_CONTROL_INTERROGATE: // // send service status update // break; case SERVICE_CONTROL_POWEREVENT: // // power event notifications // if( dwEventType == PBT_APMSUSPEND ) { iked.log.txt( LLOG_DEBUG, "ii : SERVICE_CONTROL_POWEREVENT -> PBT_APMSUSPEND\n" ); iked.halt( false ); } if( dwEventType == PBT_APMRESUMEAUTOMATIC ) iked.log.txt( LLOG_DEBUG, "ii : SERVICE_CONTROL_POWEREVENT -> PBT_APMRESUMEAUTOMATIC\n" ); if( dwEventType == PBT_APMRESUMESUSPEND ) iked.log.txt( LLOG_DEBUG, "ii : SERVICE_CONTROL_POWEREVENT -> PBT_APMRESUMESUSPEND\n" ); break; default: // // unknown service opcode // printf( "ii : unknown service opcode\n" ); return ERROR_CALL_NOT_IMPLEMENTED; } // // send service status update // if( !SetServiceStatus( service_handle, &service_status ) ) printf( "ii : unable to update service status" ); return NO_ERROR; } VOID __stdcall service_main( DWORD argc, LPTSTR * argv ) { // // Register service control handler // service_status.dwServiceType = SERVICE_WIN32; service_status.dwCurrentState = SERVICE_START_PENDING; service_status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_POWEREVENT; service_status.dwWin32ExitCode = 0; service_status.dwServiceSpecificExitCode = 0; service_status.dwCheckPoint = 0; service_status.dwWaitHint = 0; service_handle = RegisterServiceCtrlHandlerEx( SERVICE_NAME, service_ctrl, NULL ); if( service_handle == NULL ) { printf( "ii : unable to register service control handler\n" ); return; } if( iked.init( 0 ) != LIBIKE_OK ) { // // daemon initialization failed // service_status.dwCurrentState = SERVICE_STOPPED; service_status.dwCheckPoint = 0; service_status.dwWaitHint = 0; service_status.dwWin32ExitCode = -1; service_status.dwServiceSpecificExitCode = 0; SetServiceStatus( service_handle, &service_status ); printf( "ii : service failed to start\n" ); return; } // // daemon initialized // service_status.dwCurrentState = SERVICE_RUNNING; service_status.dwCheckPoint = 0; service_status.dwWaitHint = 0; SetServiceStatus( service_handle, &service_status ); printf( "ii : service started\n" ); // // run daemon main loop // iked.loop(); // // notify service has stopped // service_status.dwWin32ExitCode = 0; service_status.dwCurrentState = SERVICE_STOPPED; service_status.dwCheckPoint = 0; service_status.dwWaitHint = 0; SetServiceStatus( service_handle, &service_status ); } #endif #ifdef UNIX // // unix daemon specific section // void daemon_stop( int sig_num ) { // // stop daemon operation // iked.halt( true ); } bool daemon_pidfile_create( char * path_pid ) { if( !path_pid[ 0 ] ) return false; // // read the pid file // pid_t pid = -1; FILE * fp = fopen( path_pid, "r" ); if( fp != NULL ) { fscanf( fp, "%d", &pid ); fclose( fp ); } if( getpgid( pid ) != -1 ) { printf( "process already running as pid %d\n", pid ); return false; } fp = fopen( path_pid, "w" ); if( fp != NULL ) { fprintf( fp, "%d", getpid() ); fclose( fp ); return true; } printf( "unable to open pid file path \'%s\'\n", path_pid ); return false; } void daemon_pidfile_remove( char * path_pid ) { if( !path_pid[ 0 ] ) return; unlink( path_pid ); } #endif int main( int argc, char * argv[], char * envp[] ) { #ifdef WIN32 // // initialize winsock // WORD reqver; WSADATA wsadata; memset( &wsadata, 0, sizeof( wsadata ) ); reqver = MAKEWORD( 1, 1 ); if( WSAStartup( reqver, &wsadata ) ) { printf( "wsastartup failed\n" ); return false; } // // check command line parameters // bool service = false; for( long count = 1; count < argc; count++ ) { if( !strcmp( argv[ count ], "-service" ) ) service = true; if( !strcmp( argv[ count ], "-register" ) ) { service_add( argv[ 0 ] ); return 0; } if( !strcmp( argv[ count ], "-deregister" ) ) { service_del( argv[ 0 ] ); return 0; } } // // are we running as a service // or a foreground application // if( service ) { // // running as a service // SERVICE_TABLE_ENTRY ste[ 2 ]; ste[ 0 ].lpServiceName = SERVICE_NAME; ste[ 0 ].lpServiceProc = service_main; ste[ 1 ].lpServiceName = NULL; ste[ 1 ].lpServiceProc = NULL; if( !StartServiceCtrlDispatcher( ste ) ) printf( "ii : StartServiceCtrlDispatcher error = %d\n", GetLastError() ); } else { // // running as an application // if( iked.init( 0 ) != LIBIKE_OK ) return false; // // run daemon main loop // iked.loop(); } // // release winsock // WSACleanup(); #endif #ifdef UNIX // // check that we are root // if( getuid() ) { printf( "you must be root to run this program !!!\n" ); return LIBIKE_FAILED; } // // check command line parameters // char path_conf[ MAX_PATH ] = { 0 }; char path_log[ MAX_PATH ] = { 0 }; char path_pid[ MAX_PATH ] = { 0 }; bool service = true; long debuglevel = 0; for( long argi = 1; argi < argc; argi++ ) { if( !strcmp( argv[ argi ], "-F" ) ) { service = false; continue; } if( !strcmp( argv[ argi ], "-p" ) ) { if( ( argc - argi ) < 2 ) { printf( "you must specify a path following the -p option\n" ); return -1; } strncpy( path_pid, argv[ ++argi ], MAX_PATH ); continue; } if( !strcmp( argv[ argi ], "-f" ) ) { if( ( argc - argi ) < 2 ) { printf( "you must specify a path following the -f option\n" ); return -1; } strncpy( path_conf, argv[ ++argi ], MAX_PATH ); continue; } if( !strcmp( argv[ argi ], "-l" ) ) { if( ( argc - argi ) < 2 ) { printf( "you must specify a path following the -l option\n" ); return -1; } strncpy( path_log, argv[ ++argi ], MAX_PATH ); continue; } if( !strcmp( argv[ argi ], "-d" ) ) { if( ( argc - argi ) < 2 ) { printf( "you must specify a debug level between 0 and 6 following the -d option\n" ); return -1; } debuglevel = atol( argv[ ++argi ] ); if ( ( debuglevel < 0 ) || (debuglevel > 6) ) { printf( "you must specify a debug level between 0 and 6 following the -d option\n" ); return -1; } continue; } printf( "invalid option %s specified\n", argv[ argi ] ); return -1; } // // setup stop signal // signal( SIGINT, daemon_stop ); signal( SIGTERM, daemon_stop ); signal( SIGPIPE, SIG_IGN ); // // set config and log file paths // iked.set_files( path_conf, path_log ); // // initialize // if( iked.init( debuglevel ) != LIBIKE_OK ) return -1; // // are we running as a deamon // if( service ) daemon( 0, 0 ); // // create our pid file // if( path_pid[ 0 ] ) if( !daemon_pidfile_create( path_pid ) ) return -1; // // run daemon main loop // iked.loop(); // // remove our pidfile // if( path_pid[ 0 ] ) daemon_pidfile_remove( path_pid ); #endif return 0; } ike-2.2.1+dfsg/source/iked/xauth.h000066400000000000000000000063121223036517100167230ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ // // XAUTH abstract class // typedef class _IKED_XAUTH { public: virtual ~_IKED_XAUTH(); virtual const char * name() = 0; virtual bool auth_pwd( IKE_XAUTH & xauth ) = 0; virtual bool auth_grp( IKE_XAUTH & xauth, BDATA & group ) = 0; }IKED_XAUTH; // // XAUTH functional classes // typedef class _IKED_XAUTH_LOCAL : public _IKED_XAUTH { public: _IKED_XAUTH_LOCAL(); virtual ~_IKED_XAUTH_LOCAL(); virtual const char * name(); virtual bool auth_pwd( IKE_XAUTH & xauth ); virtual bool auth_grp( IKE_XAUTH & xauth, BDATA & group ); }IKED_XAUTH_LOCAL; #ifdef OPT_LDAP typedef class _IKED_XAUTH_LDAP : public _IKED_XAUTH { protected: bool open_conn( LDAP ** ld ); public: long version; BDATA url; BDATA base; bool subtree; BDATA bind_dn; BDATA bind_pw; BDATA attr_user; BDATA attr_group; BDATA attr_member; _IKED_XAUTH_LDAP(); virtual ~_IKED_XAUTH_LDAP(); virtual const char * name(); virtual bool auth_pwd( IKE_XAUTH & xauth ); virtual bool auth_grp( IKE_XAUTH & xauth, BDATA & group ); }IKED_XAUTH_LDAP; #endif ike-2.2.1+dfsg/source/iked/xconf.h000066400000000000000000000056421223036517100167140ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ // // XCONF abstract class // typedef struct POOL4 { in_addr addr; bool used; }POOL4; typedef class _IKED_XCONF { public: POOL4 * pool4_array; long pool4_inuse; long pool4_total; ITH_LOCK pool4_lock; IKE_XCONF config; IDB_LIST_DOMAIN domains; BDATA banner; virtual ~_IKED_XCONF(); virtual const char * name() = 0; virtual bool rslt( IDB_TUNNEL * tunnel ) = 0; bool pool4_set( in_addr & base, long bits, long max ); bool pool4_get( in_addr & addr ); bool pool4_rel( in_addr & addr ); }IKED_XCONF; // // XCONF functional classes // typedef class _IKED_XCONF_LOCAL : public _IKED_XCONF { public: _IKED_XCONF_LOCAL(); virtual ~_IKED_XCONF_LOCAL(); virtual const char * name(); virtual bool rslt( IDB_TUNNEL * tunnel ); }IKED_XCONF_LOCAL; ike-2.2.1+dfsg/source/libidb/000077500000000000000000000000001223036517100157305ustar00rootroot00000000000000ike-2.2.1+dfsg/source/libidb/CMakeLists.txt000066400000000000000000000015151223036517100204720ustar00rootroot00000000000000# # Shrew Soft VPN / Internal Object Database # Cross Platform Make File # # author : Matthew Grooms # : mgrooms@shrew.net # : Copyright 2007, Shrew Soft Inc # include_directories( ${IKE_SOURCE_DIR}/source ${IKE_SOURCE_DIR}/source/libip ${IKE_SOURCE_DIR}/source/liblog ${IKE_SOURCE_DIR}/source/libith ) add_library( ss_idb SHARED libidb.cpp base64.cpp ) target_link_libraries( ss_idb ss_ith ss_log ) set_target_properties( ss_idb PROPERTIES VERSION ${RELVER} SOVERSION ${RELVER} ) if( APPLE ) set( MACOSX_BUNDLE_BUNDLE_NAME "ShrewSoftIdb" ) set_property( TARGET ss_idb PROPERTY FRAMEWORK ON ) set_property( TARGET ss_idb PROPERTY OUTPUT_NAME ${MACOSX_BUNDLE_BUNDLE_NAME} ) endif( APPLE ) install( TARGETS ss_idb LIBRARY DESTINATION ${PATH_LIB} FRAMEWORK DESTINATION "/Library/Frameworks" ) ike-2.2.1+dfsg/source/libidb/base64.cpp000066400000000000000000000237721223036517100175330ustar00rootroot00000000000000/* OPENBSD ORIGINAL: lib/libc/net/base64.c */ /* $OpenBSD: base64.c,v 1.4 2002/01/02 23:00:10 deraadt Exp $ */ /* * Copyright (c) 1996 by Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. */ /* * Portions Copyright (c) 1995 by International Business Machines, Inc. * * International Business Machines, Inc. (hereinafter called IBM) grants * permission under its copyrights to use, copy, modify, and distribute this * Software with or without fee, provided that the above copyright notice and * all paragraphs of this notice appear in all copies, and that the name of IBM * not be used in connection with the marketing of any product incorporating * the Software or modifications thereof, without specific, written prior * permission. * * To the extent it has a right to do so, IBM grants an immunity from suit * under its patents, if any, for the use, sale or manufacture of products to * the extent that such products are used for performing Domain Name System * dynamic updates in TCP/IP networks by means of the Software. No immunity is * granted for any product per se or for any other function of any product. * * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. */ #include "base64.h" static const char Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static const char Pad64 = '='; inline bool isspace( int c ) { return ( ( ( c >= 0x09 ) && ( c <= 0x0D ) ) || ( c == 0x20 ) ); } /* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) The following encoding technique is taken from RFC 1521 by Borenstein and Freed. It is reproduced here in a slightly edited form for convenience. A 65-character subset of US-ASCII is used, enabling 6 bits to be represented per printable character. (The extra 65th character, "=", is used to signify a special processing function.) The encoding process represents 24-bit groups of input bits as output strings of 4 encoded characters. Proceeding from left to right, a 24-bit input group is formed by concatenating 3 8-bit input groups. These 24 bits are then treated as 4 concatenated 6-bit groups, each of which is translated into a single digit in the base64 alphabet. Each 6-bit group is used as an index into an array of 64 printable characters. The character referenced by the index is placed in the output string. Table 1: The Base64 Alphabet Value Encoding Value Encoding Value Encoding Value Encoding 0 A 17 R 34 i 51 z 1 B 18 S 35 j 52 0 2 C 19 T 36 k 53 1 3 D 20 U 37 l 54 2 4 E 21 V 38 m 55 3 5 F 22 W 39 n 56 4 6 G 23 X 40 o 57 5 7 H 24 Y 41 p 58 6 8 I 25 Z 42 q 59 7 9 J 26 a 43 r 60 8 10 K 27 b 44 s 61 9 11 L 28 c 45 t 62 + 12 M 29 d 46 u 63 / 13 N 30 e 47 v 14 O 31 f 48 w (pad) = 15 P 32 g 49 x 16 Q 33 h 50 y Special processing is performed if fewer than 24 bits are available at the end of the data being encoded. A full encoding quantum is always completed at the end of a quantity. When fewer than 24 input bits are available in an input group, zero bits are added (on the right) to form an integral number of 6-bit groups. Padding at the end of the data is performed using the '=' character. Since all base64 input is an integral number of octets, only the ------------------------------------------------- following cases can arise: (1) the final quantum of encoding input is an integral multiple of 24 bits; here, the final unit of encoded output will be an integral multiple of 4 characters with no "=" padding, (2) the final quantum of encoding input is exactly 8 bits; here, the final unit of encoded output will be two characters followed by two "=" padding characters, or (3) the final quantum of encoding input is exactly 16 bits; here, the final unit of encoded output will be three characters followed by one "=" padding character. */ int b64_ntop( unsigned char const *src, long srclength, char *target, long targsize) { long datalength = 0; unsigned char input[3]; unsigned char output[4]; long i; while (2 < srclength) { input[0] = *src++; input[1] = *src++; input[2] = *src++; srclength -= 3; output[0] = input[0] >> 2; output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); output[3] = input[2] & 0x3f; assert(output[0] < 64); assert(output[1] < 64); assert(output[2] < 64); assert(output[3] < 64); if (datalength + 4 > targsize) return (-1); target[datalength++] = Base64[output[0]]; target[datalength++] = Base64[output[1]]; target[datalength++] = Base64[output[2]]; target[datalength++] = Base64[output[3]]; } /* Now we worry about padding. */ if (0 != srclength) { /* Get what's left. */ input[0] = input[1] = input[2] = '\0'; for (i = 0; i < srclength; i++) input[i] = *src++; output[0] = input[0] >> 2; output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); assert(output[0] < 64); assert(output[1] < 64); assert(output[2] < 64); if (datalength + 4 > targsize) return (-1); target[datalength++] = Base64[output[0]]; target[datalength++] = Base64[output[1]]; if (srclength == 1) target[datalength++] = Pad64; else target[datalength++] = Base64[output[2]]; target[datalength++] = Pad64; } if (datalength >= targsize) return (-1); target[datalength] = '\0'; /* Returned value doesn't count \0. */ return (datalength); } /* skips all whitespace anywhere. converts characters, four at a time, starting at (or after) src from base - 64 numbers into three 8 bit bytes in the target area. it returns the number of data bytes stored at the target, or -1 on error. */ int b64_pton( char const *src, unsigned char *target, long targsize) { int tarindex, state, ch; const char *pos; state = 0; tarindex = 0; while ((ch = *src++) != '\0') { if (isspace(ch)) /* Skip whitespace anywhere. */ continue; if (ch == Pad64) break; pos = strchr(Base64, ch); if (pos == 0) /* A non-base64 character. */ return (-1); switch (state) { case 0: if (target) { if (tarindex >= targsize) return (-1); target[tarindex] = (unsigned char)(pos - Base64) << 2; } state = 1; break; case 1: if (target) { if (tarindex + 1 >= targsize) return (-1); target[tarindex] |= (pos - Base64) >> 4; target[tarindex+1] = (unsigned char)((pos - Base64) & 0x0f) << 4 ; } tarindex++; state = 2; break; case 2: if (target) { if (tarindex + 1 >= targsize) return (-1); target[tarindex] |= (pos - Base64) >> 2; target[tarindex+1] = (unsigned char)((pos - Base64) & 0x03) << 6; } tarindex++; state = 3; break; case 3: if (target) { if (tarindex >= targsize) return (-1); target[tarindex] |= (pos - Base64); } tarindex++; state = 0; break; } } /* * We are done decoding Base-64 chars. Let's see if we ended * on a byte boundary, and/or with erroneous trailing characters. */ if (ch == Pad64) { /* We got a pad char. */ ch = *src++; /* Skip it, get next. */ switch (state) { case 0: /* Invalid = in first position */ case 1: /* Invalid = in second position */ return (-1); case 2: /* Valid, means one byte of info */ /* Skip any number of spaces. */ for (; ch != '\0'; ch = *src++) if (!isspace(ch)) break; /* Make sure there is another trailing = sign. */ if (ch != Pad64) return (-1); ch = *src++; /* Skip the = */ /* Fall through to "single trailing =" case. */ /* FALLTHROUGH */ case 3: /* Valid, means two bytes of info */ /* * We know this char is an =. Is there anything but * whitespace after it? */ for (; ch != '\0'; ch = *src++) if (!isspace(ch)) return (-1); /* * Now make sure for cases 2 and 3 that the "extra" * bits that slopped past the last full byte were * zeros. If we don't check them, they become a * subliminal channel. */ if (target && target[tarindex] != 0) return (-1); } } else { /* * We ended by seeing the end of the string. Make sure we * have no partial bytes lying around. */ if (state != 0) return (-1); } return (tarindex); } ike-2.2.1+dfsg/source/libidb/base64.h000066400000000000000000000050761223036517100171750ustar00rootroot00000000000000/* $Id: base64.h,v 1.6 2003/08/29 16:59:52 mouring Exp $ */ /* * Copyright (c) 1996 by Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. */ /* * Portions Copyright (c) 1995 by International Business Machines, Inc. * * International Business Machines, Inc. (hereinafter called IBM) grants * permission under its copyrights to use, copy, modify, and distribute this * Software with or without fee, provided that the above copyright notice and * all paragraphs of this notice appear in all copies, and that the name of IBM * not be used in connection with the marketing of any product incorporating * the Software or modifications thereof, without specific, written prior * permission. * * To the extent it has a right to do so, IBM grants an immunity from suit * under its patents, if any, for the use, sale or manufacture of products to * the extent that such products are used for performing Domain Name System * dynamic updates in TCP/IP networks by means of the Software. No immunity is * granted for any product per se or for any other function of any product. * * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. */ #ifndef _BSD_BASE64_H #define _BSD_BASE64_H #include #include #include "inttypes.h" int b64_ntop( unsigned char const *src, long srclength, char *target, long targsize ); int b64_pton( char const *src, unsigned char *target, long targsize ); #endif /* _BSD_BASE64_H */ ike-2.2.1+dfsg/source/libidb/libidb.cpp000066400000000000000000000330231223036517100176620ustar00rootroot00000000000000/* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "libidb.h" #include "base64.h" //============================================================================== // basic data class // _BDATA & _BDATA::operator =( _BDATA & bdata ) { del(); set( bdata ); return *this; } bool _BDATA::operator ==( _BDATA & bdata ) { if( bdata.size() != size() ) return false; return ( memcmp( bdata.buff(), buff(), size() ) == 0 ); } bool _BDATA::operator !=( _BDATA & bdata ) { return !( *this == bdata ); } _BDATA::_BDATA() { data_buff = NULL; data_real = 0; data_size = 0; data_oset = 0; } _BDATA::_BDATA( _BDATA & bdata ) { _BDATA(); *this = bdata; } _BDATA::~_BDATA() { del( true ); } size_t _BDATA::grow( size_t new_real ) { if( new_real >= ( 1024 * 1024 ) ) return data_real; if( data_real < new_real ) { unsigned char * new_buff = new unsigned char[ new_real ]; if( new_buff == NULL ) return data_real; if( data_buff != NULL ) { memcpy( new_buff, data_buff, data_real ); delete [] data_buff; } data_buff = new_buff; data_real = new_real; } return data_real; } size_t _BDATA::size( size_t new_size ) { if( new_size != ~0 ) { if( grow( new_size ) < new_size ) return data_size; data_size = new_size; } if( data_oset > data_size ) data_oset = data_size; return data_size; } size_t _BDATA::oset( size_t new_oset ) { if( new_oset != ~0 ) if( data_size >= new_oset ) data_oset = new_oset; return data_oset; } char * _BDATA::text() { return ( char * ) data_buff; } unsigned char * _BDATA::buff() { return data_buff; } bool _BDATA::hex_encode( bool upper_case ) { BDATA hex_temp; size_t hex_oset = 0; while( hex_oset < data_size ) { uint8_t temp1 = data_buff[ hex_oset++ ]; uint8_t temp2 = temp1 >> 4; uint8_t temp3 = temp1 & 0xf; if( temp2 <= 9 ) temp2 += 48; else { if( upper_case ) temp2 += 55; else temp2 += 87; } hex_temp.add( temp2, 1 ); if( temp3 <= 9 ) temp3 += 48; else { if( upper_case ) temp3 += 55; else temp3 += 87; } hex_temp.add( temp3, 1 ); } *this = hex_temp; return true; } bool _BDATA::hex_decode() { BDATA hex_temp; size_t hex_oset = 0; if( size() & 1 ) return false; while( hex_oset < data_size ) { uint8_t temp1 = data_buff[ hex_oset++ ]; uint8_t temp2 = data_buff[ hex_oset++ ]; if( ( temp1 >= 48 ) && ( temp1 <= 57 ) ) temp1 -= 48; if( ( temp1 >= 65 ) && ( temp1 <= 70 ) ) temp1 -= 55; if( ( temp1 >= 97 ) && ( temp1 <= 102 ) ) temp1 -= 87; if( ( temp2 >= 48 ) && ( temp2 <= 57 ) ) temp2 -= 48; if( ( temp2 >= 65 ) && ( temp2 <= 70 ) ) temp2 -= 55; if( ( temp2 >= 97 ) && ( temp2 <= 102 ) ) temp2 -= 87; int temp3 = ( temp1 << 4 ) | temp2; hex_temp.add( temp3, 1 ); } hex_temp.size( data_size >> 1 ); *this = hex_temp; return true; } bool _BDATA::base64_encode() { BDATA b64_temp; size_t b64_size; if( !b64_temp.size( size() * 2 + 2 ) ) return false; b64_size = b64_ntop( buff(), ( long ) size(), b64_temp.text(), ( long ) b64_temp.size() ); if( b64_size == -1 ) return false; b64_temp.size( b64_size + 1 ); b64_temp.buff()[ b64_size ] = 0; *this = b64_temp; return true; } bool _BDATA::base64_decode() { BDATA b64_temp; size_t b64_size; if( !b64_temp.size( size() ) ) return false; b64_size = b64_pton( text(), b64_temp.buff(), ( long ) b64_temp.size() ); if( b64_size == -1 ) return false; b64_temp.size( b64_size ); *this = b64_temp; return true; } bool _BDATA::set( _BDATA & bdata, size_t oset ) { return set( ( char * ) bdata.buff(), bdata.size(), oset ); } bool _BDATA::set( int value, size_t size, size_t oset ) { if( !set( ( void * ) NULL, size ) ) return false; memset( data_buff + oset, value, size ); return true; } bool _BDATA::set( void * buff, size_t size, size_t oset ) { size_t new_size = oset + size; if( grow( new_size ) < new_size ) return false; if( buff != NULL ) memcpy( data_buff + oset, buff, size ); if( data_size < new_size ) data_size = new_size; return true; } bool _BDATA::set( char * buff, size_t size, size_t oset ) { return set( ( void * ) buff, size, oset ); } bool _BDATA::set( const char * buff, size_t size, size_t oset ) { return set( ( void * ) buff, size, oset ); } bool _BDATA::ins( _BDATA & bdata, size_t oset ) { return ins( bdata.buff(), bdata.size(), oset ); } bool _BDATA::ins( int value, size_t size, size_t oset ) { if( !ins( ( void * ) NULL, size, oset ) ) return false; memset( data_buff + oset, value, size ); return true; } bool _BDATA::ins( void * buff, size_t size, size_t oset ) { size_t new_size = data_size + size; if( new_size < ( oset + size ) ) new_size = ( oset + size ); if( grow( new_size ) < new_size ) return false; if( oset < data_size ) memmove( data_buff + oset + size, data_buff + oset, data_size - oset ); if( buff ) memcpy( data_buff + oset, buff, size ); if( data_size < new_size ) data_size = new_size; return true; } bool _BDATA::ins( char * buff, size_t size, size_t oset ) { return ins( ( void * ) buff, size, oset ); } bool _BDATA::ins( const char * buff, size_t size, size_t oset ) { return ins( ( void * ) buff, size, oset ); } bool _BDATA::add( _BDATA & bdata ) { return add( bdata.buff(), bdata.size() ); } bool _BDATA::add( int value, size_t size ) { if( !add( ( void * ) NULL, size ) ) return false; memset( data_buff + data_size - size, value, size ); return true; } bool _BDATA::add( void * buff, size_t size ) { size_t new_size = data_size + size; if( grow( new_size ) < new_size ) return false; if( buff ) memcpy( data_buff + data_size, buff, size ); data_size = new_size; return true; } bool _BDATA::add( char * buff, size_t size ) { return add( ( void * ) buff, size ); } bool _BDATA::add( const char * buff, size_t size ) { return add( ( void * ) buff, size ); } bool _BDATA::get( _BDATA & bdata, size_t size ) { size_t left = data_size - data_oset; if( size == BDATA_ALL ) size = left; if( size > left ) return false; bdata.size( size ); return get( bdata.buff(), bdata.size() ); } bool _BDATA::get( char * buff, size_t size ) { return get( ( void * ) buff, size ); } bool _BDATA::get( void * buff, size_t size ) { if( size > ( data_size - data_oset ) ) return false; // copy the user requested data if( buff ) memcpy( buff, data_buff + data_oset, size ); // set our new offset data_oset += size; return true; } void _BDATA::del( bool null ) { if( data_buff ) { if( null ) memset( data_buff, 0, data_real ); delete [] data_buff; } data_buff = NULL; data_real = 0; data_size = 0; data_oset = 0; } bool _BDATA::file_load( FILE * fp ) { if( fp == NULL ) return false; del(); while( true ) { int next = fgetc( fp ); if( next == EOF ) break; add( next, 1 ); } return ( data_size > 0 ); } bool _BDATA::file_load( const char * path ) { #ifdef WIN32 FILE * fp; if( fopen_s( &fp, path, "rb" ) ) return false; #else FILE * fp = fopen( path, "r" ); if( fp == NULL ) return false; #endif bool result = file_load( fp ); fclose( fp ); return result; } bool _BDATA::file_save( FILE * fp ) { if( fp == NULL ) return false; size_t count = data_size; size_t index = 0; for( ; index < count; index++ ) fputc( data_buff[ index ], fp ); return true; } bool _BDATA::file_save( const char * path ) { #ifdef WIN32 FILE * fp; if( fopen_s( &fp, path, "wb" ) ) return false; #else FILE * fp = fopen( path, "w" ); if( fp == NULL ) return false; #endif bool result = file_save( fp ); fclose( fp ); return result; } //============================================================================== // standard IDB list classes // _IDB_ENTRY::_IDB_ENTRY() { } _IDB_ENTRY::~_IDB_ENTRY() { } _IDB_LIST::_IDB_LIST() { entry_list = NULL; entry_max = 0; entry_num = 0; } _IDB_LIST::~_IDB_LIST() { if( entry_list != NULL ) delete [] entry_list; entry_list = NULL; } long _IDB_LIST::count() { return entry_num; } void _IDB_LIST::clean() { while( count() ) delete del_entry( 0 ); } bool _IDB_LIST::grow() { // allocate a new stack of pointers that will // be larger that the last by GROW_SIZE IDB_ENTRY ** new_entry_list = new IDB_ENTRY * [ entry_max + GROW_SIZE ]; if( new_entry_list == NULL ) return false; // initialize our new stack of pointers to null and memset( new_entry_list, 0, ( entry_max + GROW_SIZE ) * sizeof( IDB_ENTRY * ) ); // copy our old pointer stack to our new pointer stack memcpy( new_entry_list, entry_list, entry_max * sizeof( IDB_ENTRY * ) ); // free our old pointer stack if( entry_list != NULL ) delete [] entry_list; //replace it with our new larger pointer stack entry_list = new_entry_list; // store our new item_capacity entry_max += GROW_SIZE; return true; } bool _IDB_LIST::add_entry( IDB_ENTRY * entry ) { // sanity check for valid pointer if( entry == NULL ) return false; // make sure we have enough room in our stack, // grow if neccesary if( entry_num == entry_max ) if( !grow() ) return false; // store our new string in the next available // slot in the stack entry_list[ entry_num ] = entry; // increment our list count entry_num++; return true; } bool _IDB_LIST::del_entry( IDB_ENTRY * entry ) { // sanity check for valid pointer if( entry == NULL ) return false; // attempt to match our item to an item // in our stack long index = 0; while( 1 ) { // check for a match if( entry_list[ index ] == entry ) break; // if we have exausted all pointers in our // stack then return false if( index == ( entry_num - 1 ) ) return false; index++; } // copy the trailing pointers in our list // to fill the empty slot int trailing_pointers = entry_num - index - 1; if( trailing_pointers ) memmove( &entry_list[ index ], &entry_list[ index + 1 ], trailing_pointers * sizeof( IDB_ENTRY * ) ); // null previously last used pointer in // list and decrement count entry_list[ entry_num - 1 ] = 0; entry_num--; return true; } IDB_ENTRY * _IDB_LIST::del_entry( int index ) { // sanity check for valid index if( ( index >= entry_num ) || ( index < 0 ) ) return NULL; // store the item for return IDB_ENTRY * entry = entry_list[ index ]; // copy the trailing pointers in our list // to fill the empty slot int trailing_pointers = entry_num - index - 1; if( trailing_pointers ) memmove( &entry_list[ index ], &entry_list[ index + 1 ], trailing_pointers * sizeof( IDB_ENTRY * ) ); // null previously last used pointer in // list and decrement count entry_list[ entry_num - 1 ] = 0; entry_num--; return entry; } IDB_ENTRY * _IDB_LIST::get_entry( int index ) { // sanity check for valid index if( ( index >= entry_num ) || ( index < 0 ) ) return NULL; // return the requested item return entry_list[ index ]; } ike-2.2.1+dfsg/source/libidb/libidb.h000066400000000000000000000137121223036517100173320ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #ifndef _IDB_H_ #define _IDB_H_ #include #include "export.h" //============================================================================== // Basic data class //============================================================================== #define BDATA_ALL ~0 typedef class DLX _BDATA { protected: unsigned char * data_buff; size_t data_real; size_t data_size; size_t data_oset; size_t grow( size_t new_size = ~0 ); public: _BDATA & operator =( _BDATA & bdata ); bool operator ==( _BDATA & bdata ); bool operator !=( _BDATA & bdata ); _BDATA(); _BDATA( _BDATA & bdata ); virtual ~_BDATA(); size_t oset( size_t new_oset = ~0 ); size_t size( size_t new_size = ~0 ); char * text(); unsigned char * buff(); bool hex_encode( bool upper_case = false ); bool hex_decode(); bool base64_encode(); bool base64_decode(); bool set( _BDATA & bdata, size_t oset = 0 ); bool set( int value, size_t size, size_t oset = 0 ); bool set( void * buff, size_t size, size_t oset = 0 ); bool set( char * buff, size_t size, size_t oset = 0 ); bool set( const char * buff, size_t size, size_t oset = 0 ); bool ins( _BDATA & bdata, size_t oset = 0 ); bool ins( int value, size_t size, size_t oset = 0 ); bool ins( void * buff, size_t size, size_t oset = 0 ); bool ins( char * buff, size_t size, size_t oset = 0 ); bool ins( const char * buff, size_t size, size_t oset = 0 ); bool add( _BDATA & bdata ); bool add( int value, size_t size ); bool add( void * buff, size_t size ); bool add( char * buff, size_t size ); bool add( const char * buff, size_t size ); bool get( _BDATA & bdata, size_t size = BDATA_ALL ); bool get( void * buff, size_t size ); bool get( char * buff, size_t size ); void del( bool null = false ); bool file_load( FILE * fp ); bool file_load( const char * path ); bool file_save( FILE * fp ); bool file_save( const char * path ); }BDATA, *PBDATA; //============================================================================== // standard IDB list classes //============================================================================== typedef class DLX _IDB_ENTRY { public: _IDB_ENTRY(); virtual ~_IDB_ENTRY(); }IDB_ENTRY; #define GROW_SIZE 16 typedef class DLX _IDB_LIST { public: IDB_ENTRY ** entry_list; long entry_max; long entry_num; bool grow(); _IDB_LIST(); virtual ~_IDB_LIST(); long count(); virtual void clean(); bool add_entry( IDB_ENTRY * entry ); bool del_entry( IDB_ENTRY * entry ); IDB_ENTRY * del_entry( int index ); IDB_ENTRY * get_entry( int index ); }IDB_LIST; /* //============================================================================== // reference counted IDB classes //============================================================================== class _IDB_RC_LIST; #define IDB_FLAG_DEAD 1 #define IDB_FLAG_IMMEDIATE 2 #define IDB_FLAG_ENDCALLED 4 typedef class DLX _IDB_RC_ENTRY : public IDB_ENTRY { protected: long idb_flags; long idb_refcount; inline long chkflags( long flags ) { return ( idb_flags & flags ); } inline long setflags( long flags ) { return idb_flags |= flags; } inline long clrflags( long flags ) { return idb_flags &= ~flags; } void callend(); virtual void beg() = 0; virtual void end() = 0; public: _IDB_RC_ENTRY(); virtual ~_IDB_RC_ENTRY(); virtual const char * name() = 0; virtual _IDB_RC_LIST * list() = 0; bool add( bool lock ); void inc( bool lock ); bool dec( bool lock, bool setdel = false ); }IDB_RC_ENTRY; typedef class DLX _IDB_RC_LIST : public IDB_LIST { public: _IDB_RC_LIST(); virtual ~_IDB_RC_LIST(); virtual void clean(); virtual bool lock() = 0; virtual bool unlock() = 0; }IDB_RC_LIST; */ #endif ike-2.2.1+dfsg/source/libike/000077500000000000000000000000001223036517100157425ustar00rootroot00000000000000ike-2.2.1+dfsg/source/libike/CMakeLists.txt000066400000000000000000000020301223036517100204750ustar00rootroot00000000000000 # # Shrew Soft VPN / IKE Daemon Interface Library # Cross Platform Make File # # author : Matthew Grooms # : mgrooms@shrew.net # : Copyright 2007, Shrew Soft Inc # include_directories( ${IKE_SOURCE_DIR}/source ${IKE_SOURCE_DIR}/source/iked ${IKE_SOURCE_DIR}/source/libike ${IKE_SOURCE_DIR}/source/libidb ${IKE_SOURCE_DIR}/source/libith ${IKE_SOURCE_DIR}/source/liblog ${IKE_SOURCE_DIR}/source/libip ) add_library( ss_ike SHARED client.cpp config.cpp manager.cpp manager.file.cpp libike.cpp ) target_link_libraries( ss_ike ss_idb ss_ith crypto ) set_target_properties( ss_ike PROPERTIES VERSION ${RELVER} SOVERSION ${RELVER} ) if( APPLE ) set( MACOSX_BUNDLE_BUNDLE_NAME "ShrewSoftIke" ) set_property( TARGET ss_ike PROPERTY FRAMEWORK ON ) set_property( TARGET ss_ike PROPERTY OUTPUT_NAME ${MACOSX_BUNDLE_BUNDLE_NAME} ) endif( APPLE ) install( TARGETS ss_ike LIBRARY DESTINATION ${PATH_LIB} FRAMEWORK DESTINATION "/Library/Frameworks" ) ike-2.2.1+dfsg/source/libike/client.cpp000066400000000000000000001106251223036517100177310ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "client.h" //============================================================================== // Base IKEC class //============================================================================== bool _CLIENT::run_init() { memset( &peer, 0, sizeof( peer ) ); memset( &xconf, 0, sizeof( xconf ) ); // // load the config into ipsecc // long numb; char text[ MAX_CONFSTRING ]; BDATA btext; // // ---------- PEER CONFIG ---------- // // default values peer.contact = IPSEC_CONTACT_CLIENT; peer.plcy_mode = POLICY_MODE_CONFIG; peer.notify = true; // netowrk host if( !config.get_string( "network-host", text, MAX_CONFSTRING, 0 ) ) { log( STATUS_FAIL, "config error : network-host undefined\n" ); return false; } char * host = text; while( host && * host == ' ' ) host++; if( inet_addr( host ) != INADDR_NONE ) { peer.saddr.saddr4.sin_family = AF_INET; peer.saddr.saddr4.sin_addr.s_addr = inet_addr( host ); } else { struct hostent * hp = gethostbyname( host ); if( !hp ) { log( STATUS_FAIL, "config error : cannot resolve address for host %s\n", host ); return false; } peer.saddr.saddr4.sin_family = hp->h_addrtype; memcpy( &peer.saddr.saddr4.sin_addr, hp->h_addr, hp->h_length ); } // network port if( !config.get_number( "network-ike-port", &numb ) ) { log( STATUS_FAIL, "config error : network-ike-port undefined\n" ); return false; } peer.saddr.saddr4.sin_port = htons( ( unsigned short ) numb ); // client auto config mode peer.xconf_mode = CONFIG_MODE_NONE; if( config.get_string( "client-auto-mode", text, MAX_CONFSTRING, 0 ) ) { if( !strcmp( "push", text ) ) peer.xconf_mode = CONFIG_MODE_PUSH; if( !strcmp( "pull", text ) ) peer.xconf_mode = CONFIG_MODE_PULL; if( !strcmp( "dhcp", text ) ) peer.xconf_mode = CONFIG_MODE_DHCP; } // nat-t enable peer.natt_mode = IPSEC_NATT_DISABLE; peer.natt_port = htons( 4500 ); peer.natt_rate = 30; #ifdef OPT_NATT if( config.get_string( "network-natt-mode", text, MAX_CONFSTRING, 0 ) ) { if( !strcmp( "enable", text ) ) { peer.natt_mode = IPSEC_NATT_ENABLE; xconf.rqst |= IPSEC_OPTS_CISCO_UDP; } if( !strcmp( "force", text ) ) peer.natt_mode = IPSEC_NATT_FORCE_RFC; if( !strcmp( "force-draft", text ) ) peer.natt_mode = IPSEC_NATT_FORCE_DRAFT; if( !strcmp( "force-rfc", text ) ) peer.natt_mode = IPSEC_NATT_FORCE_RFC; if( !strcmp( "force-cisco-udp", text ) ) { peer.natt_mode = IPSEC_NATT_FORCE_CISCO; peer.natt_port = htons( 10000 ); xconf.rqst |= IPSEC_OPTS_CISCO_UDP; } // nat-t udp port if( config.get_number( "network-natt-port", &numb ) ) peer.natt_port = htons( ( unsigned short ) numb ); // nat-t keep-alive rate if( config.get_number( "network-natt-rate", &numb ) ) peer.natt_rate = numb; } #endif // ike fragmentation enable peer.frag_esp_mode = IPSEC_FRAG_DISABLE; peer.frag_ike_mode = IPSEC_FRAG_DISABLE; if( config.get_string( "network-frag-mode", text, MAX_CONFSTRING, 0 ) ) { if( !strcmp( "enable", text ) ) peer.frag_ike_mode = IPSEC_FRAG_ENABLE; if( !strcmp( "force", text ) ) peer.frag_ike_mode = IPSEC_FRAG_FORCE; // ike fragmentation size peer.frag_ike_size = 520; if( !config.get_number( "network-frag-size", &numb ) ) peer.frag_ike_size = numb; } // dpd enable peer.dpd_mode = IPSEC_DPD_DISABLE; peer.dpd_delay = 15; peer.dpd_retry = 5; numb = 0; config.get_number( "network-dpd-enable", &numb ); if( numb == 1 ) peer.dpd_mode = IPSEC_DPD_ENABLE; // isakmp notify numb = 0; config.get_number( "network-notify-enable", &numb ); if( numb ) peer.notify = true; // request motd banner numb = 0; config.get_number( "client-banner-enable", &numb ); if( numb ) xconf.rqst |= IPSEC_OPTS_BANNER; // // ---------- IDENTITY CONFIG ---------- // // client identification type peer.idtype_l = 255; if( !config.get_string( "ident-client-type", text, MAX_CONFSTRING, 0 ) ) { log( STATUS_FAIL, "config error : ident-client-type undefined\n" ); return false; } if( !strcmp( "none", text ) ) peer.idtype_l = ISAKMP_ID_NONE; if( !strcmp( "asn1dn", text ) ) peer.idtype_l = ISAKMP_ID_ASN1_DN; if( !strcmp( "keyid", text ) ) peer.idtype_l = ISAKMP_ID_KEY_ID; if( !strcmp( "fqdn", text ) ) peer.idtype_l = ISAKMP_ID_FQDN; if( !strcmp( "ufqdn", text ) ) peer.idtype_l = ISAKMP_ID_USER_FQDN; if( !strcmp( "address", text ) ) peer.idtype_l = ISAKMP_ID_IPV4_ADDR; if( peer.idtype_l == 255 ) { log( STATUS_FAIL, "config error : ident-client-type is invalid\n" ); return false; } // server identification type peer.idtype_r = 255; if( !config.get_string( "ident-server-type", text, MAX_CONFSTRING, 0 ) ) { log( STATUS_FAIL, "config error : ident-server-idtype undefined\n" ); return false; } if( !strcmp( "any", text ) ) peer.idtype_r = ISAKMP_ID_NONE; if( !strcmp( "asn1dn", text ) ) peer.idtype_r = ISAKMP_ID_ASN1_DN; if( !strcmp( "keyid", text ) ) peer.idtype_r = ISAKMP_ID_KEY_ID; if( !strcmp( "fqdn", text ) ) peer.idtype_r = ISAKMP_ID_FQDN; if( !strcmp( "ufqdn", text ) ) peer.idtype_r = ISAKMP_ID_USER_FQDN; if( !strcmp( "address", text ) ) peer.idtype_r = ISAKMP_ID_IPV4_ADDR; if( peer.idtype_r == 255 ) { log( STATUS_FAIL, "config error : ident-server-type is invalid\n" ); return false; } // // ---------- IKSAMP PROPOSAL ---------- // // phase1 exchange mode if( !config.get_string( "phase1-exchange", text, MAX_CONFSTRING, 0 ) ) { log( STATUS_FAIL, "config error : phase1-exchange undefined\n" ); return false; } if( !strcmp( "main", text ) ) peer.exchange = ISAKMP_EXCH_IDENT_PROTECT; if( !strcmp( "aggressive", text ) ) peer.exchange = ISAKMP_EXCH_AGGRESSIVE; if( !peer.exchange ) { log( STATUS_FAIL, "config error : phase1-exchange is invalid\n" ); return false; } memset( &proposal_isakmp, 0, sizeof( proposal_isakmp ) ); // defaults proposal_isakmp.proto = ISAKMP_PROTO_ISAKMP; proposal_isakmp.xform = ISAKMP_KEY_IKE; // phase1 cipher type if( !config.get_string( "phase1-cipher", text, MAX_CONFSTRING, 0 ) ) { log( STATUS_FAIL, "config error : phase1-cipher undefined\n" ); return false; } if( !strcmp( "auto", text ) ) proposal_isakmp.ciph_id = 0; if( !strcmp( "aes", text ) ) proposal_isakmp.ciph_id = IKE_CIPHER_AES; if( !strcmp( "blowfish", text ) ) proposal_isakmp.ciph_id = IKE_CIPHER_BLOWFISH; if( !strcmp( "3des", text ) ) proposal_isakmp.ciph_id = IKE_CIPHER_3DES; if( !strcmp( "cast", text ) ) proposal_isakmp.ciph_id = IKE_CIPHER_CAST; if( !strcmp( "des", text ) ) proposal_isakmp.ciph_id = IKE_CIPHER_DES; // phase1 cipher keylength if( ( proposal_isakmp.ciph_id == IKE_CIPHER_AES ) || ( proposal_isakmp.ciph_id == IKE_CIPHER_BLOWFISH ) ) { if( !config.get_number( "phase1-keylen", &numb ) ) { log( STATUS_FAIL, "config error : phase1-keylen undefined\n" ); return false; } proposal_isakmp.ciph_kl = ( unsigned short ) numb; } // phase1 hash type if( !config.get_string( "phase1-hash", text, MAX_CONFSTRING, 0 ) ) { log( STATUS_FAIL, "config error : phase1-hash undefined\n" ); return false; } if( !strcmp( "auto", text ) ) proposal_isakmp.hash_id = 0; if( !strcmp( "md5", text ) ) proposal_isakmp.hash_id = IKE_HASH_MD5; if( !strcmp( "sha1", text ) ) proposal_isakmp.hash_id = IKE_HASH_SHA1; if( !strcmp( "sha2-256", text ) ) proposal_isakmp.hash_id = IKE_HASH_SHA2_256; if( !strcmp( "sha2-384", text ) ) proposal_isakmp.hash_id = IKE_HASH_SHA2_384; if( !strcmp( "sha2-512", text ) ) proposal_isakmp.hash_id = IKE_HASH_SHA2_512; // phase1 dh group description if( !config.get_number( "phase1-dhgroup", &numb ) ) { log( STATUS_FAIL, "config error : phase1-dhgroup undefined\n" ); return false; } proposal_isakmp.dhgr_id = ( unsigned short ) numb; // phase1 authentication mode if( !config.get_string( "auth-method", text, MAX_CONFSTRING, 0 ) ) { log( STATUS_FAIL, "config error : auth-method undefined\n" ); return false; } if( !strcmp( "hybrid-rsa-xauth", text ) ) proposal_isakmp.auth_id = HYBRID_AUTH_INIT_RSA; if( !strcmp( "hybrid-grp-xauth", text ) ) { proposal_isakmp.auth_id = HYBRID_AUTH_INIT_RSA; xconf.opts |= IPSEC_OPTS_CISCO_GRP; } if( !strcmp( "mutual-rsa-xauth", text ) ) proposal_isakmp.auth_id = XAUTH_AUTH_INIT_RSA; if( !strcmp( "mutual-psk-xauth", text ) ) proposal_isakmp.auth_id = XAUTH_AUTH_INIT_PSK; if( !strcmp( "mutual-rsa", text ) ) proposal_isakmp.auth_id = IKE_AUTH_SIG_RSA; if( !strcmp( "mutual-psk", text ) ) proposal_isakmp.auth_id = IKE_AUTH_PRESHARED_KEY; // phase1 lifetime if( config.get_number( "phase1-life-secs", &numb ) ) proposal_isakmp.life_sec = numb; if( config.get_number( "phase1-life-kbytes", &numb ) ) proposal_isakmp.life_kbs = numb; // // ---------- ESP PROPOSAL ---------- // memset( &proposal_esp, 0, sizeof( proposal_esp ) ); // defaults proposal_esp.proto = ISAKMP_PROTO_IPSEC_ESP; proposal_esp.encap = 1; // phase2 transform type if( !config.get_string( "phase2-transform", text, MAX_CONFSTRING, 0 ) ) { log( STATUS_FAIL, "config error : phase2-transform undefined\n" ); return false; } if( !strcmp( "auto", text ) ) proposal_esp.xform = 0; if( !strcmp( "esp-aes", text ) ) proposal_esp.xform = ISAKMP_ESP_AES; if( !strcmp( "esp-blowfish", text ) ) proposal_esp.xform = ISAKMP_ESP_BLOWFISH; if( !strcmp( "esp-3des", text ) ) proposal_esp.xform = ISAKMP_ESP_3DES; if( !strcmp( "esp-cast", text ) ) proposal_esp.xform = ISAKMP_ESP_CAST; if( !strcmp( "esp-des", text ) ) proposal_esp.xform = ISAKMP_ESP_DES; // phase2 transform keylength if( ( proposal_esp.xform == ISAKMP_ESP_AES ) || ( proposal_esp.xform == ISAKMP_ESP_BLOWFISH ) ) { if( !config.get_number( "phase2-keylen", &numb ) ) { log( STATUS_FAIL, "config error : phase2-keylen undefined\n" ); return false; } proposal_esp.ciph_kl = ( unsigned short ) numb; } // phase2 hmac type if( !config.get_string( "phase2-hmac", text, MAX_CONFSTRING, 0 ) ) { log( STATUS_FAIL, "config error : phase2-hmac undefined\n" ); return false; } if( !strcmp( "auto", text ) ) proposal_esp.hash_id = 0; if( !strcmp( "md5", text ) ) proposal_esp.hash_id = ISAKMP_AUTH_HMAC_MD5; if( !strcmp( "sha1", text ) ) proposal_esp.hash_id = ISAKMP_AUTH_HMAC_SHA1; if( !strcmp( "sha2-256", text ) ) proposal_esp.hash_id = ISAKMP_AUTH_HMAC_SHA2_256; if( !strcmp( "sha2-384", text ) ) proposal_esp.hash_id = ISAKMP_AUTH_HMAC_SHA2_384; if( !strcmp( "sha2-512", text ) ) proposal_esp.hash_id = ISAKMP_AUTH_HMAC_SHA2_512; // phase2 pfs group description proposal_esp.dhgr_id = 0; if( config.get_number( "phase2-pfsgroup", &numb ) ) { if( !numb ) xconf.rqst |= IPSEC_OPTS_PFS; if( ( numb == IKE_GRP_GROUP1 ) || ( numb == IKE_GRP_GROUP2 ) || ( numb == IKE_GRP_GROUP5 ) || ( numb == IKE_GRP_GROUP14 ) || ( numb == IKE_GRP_GROUP15 ) || ( numb == IKE_GRP_GROUP16 ) || ( numb == IKE_GRP_GROUP17 ) || ( numb == IKE_GRP_GROUP18 ) ) proposal_esp.dhgr_id = ( unsigned short ) numb; } // phase2 lifetimes if( config.get_number( "phase2-life-secs", &numb ) ) proposal_esp.life_sec = numb; if( config.get_number( "phase2-life-kbytes", &numb ) ) proposal_esp.life_kbs = numb; // // ---------- IPCOMP PROPOSAL ---------- // memset( &proposal_ipcomp, 0, sizeof( proposal_ipcomp ) ); // defaults proposal_ipcomp.proto = ISAKMP_PROTO_IPCOMP; proposal_ipcomp.encap = 0; // ipcomp transform type if( !config.get_string( "ipcomp-transform", text, MAX_CONFSTRING, 0 ) ) { log( STATUS_FAIL, "config error : ipcomp-transform undefined\n" ); return false; } if( !strcmp( "none", text ) ) proposal_ipcomp.xform = ISAKMP_IPCOMP_NONE; if( !strcmp( "deflate", text ) ) proposal_ipcomp.xform = ISAKMP_IPCOMP_DEFLATE; if( !strcmp( "lzs", text ) ) proposal_ipcomp.xform = ISAKMP_IPCOMP_LZS; if( config.get_number( "phase2-life-secs", &numb ) ) proposal_ipcomp.life_sec = numb; if( config.get_number( "phase2-life-kbytes", &numb ) ) proposal_ipcomp.life_kbs = numb; // // ---------- CLIENT CONFIG ---------- // // unity save password option if( ( proposal_isakmp.auth_id == XAUTH_AUTH_INIT_PSK ) || ( proposal_isakmp.auth_id == XAUTH_AUTH_INIT_RSA ) || ( proposal_isakmp.auth_id == HYBRID_AUTH_INIT_RSA ) ) if( ( peer.xconf_mode == CONFIG_MODE_PULL ) || ( peer.xconf_mode == CONFIG_MODE_PUSH ) ) xconf.rqst |= IPSEC_OPTS_SAVEPW; // network interface type if( !config.get_string( "client-iface", text, MAX_CONFSTRING, 0 ) ) { log( STATUS_FAIL, "config error : client-iface undefined\n" ); return false; } if( !strcmp( "virtual", text ) || !strcmp( "random", text ) ) { xconf.opts |= ( IPSEC_OPTS_ADDR | IPSEC_OPTS_MASK ); // virtual adapter with assgined address if( !strcmp( "virtual", text ) ) { numb = 1; config.get_number( "client-addr-auto", &numb ); if( numb ) { // auto address configuration xconf.rqst |= ( IPSEC_OPTS_ADDR | IPSEC_OPTS_MASK ); } else { // static address configuration if( !config.get_string( "client-ip-addr", text, MAX_CONFSTRING, 0 ) ) { log( STATUS_FAIL, "config error : client-ip-addr undefined\n" ); return false; } xconf.addr.s_addr = inet_addr( text ); if( !config.get_string( "client-ip-mask", text, MAX_CONFSTRING, 0 ) ) { log( STATUS_FAIL, "config error : client-ip-mask undefined\n" ); return false; } xconf.mask.s_addr = inet_addr( text ); } } // virtual adapter with randomized address if( !strcmp( "random", text ) ) { // random address configuration if( !config.get_string( "client-ip-addr", text, MAX_CONFSTRING, 0 ) ) { log( STATUS_FAIL, "config error : client-ip-addr undefined\n" ); return false; } xconf.addr.s_addr = inet_addr( text ); if( !config.get_string( "client-ip-mask", text, MAX_CONFSTRING, 0 ) ) { log( STATUS_FAIL, "config error : client-ip-mask undefined\n" ); return false; } xconf.mask.s_addr = inet_addr( text ); // randomize address uint32_t addr = rand(); addr &= ~xconf.mask.s_addr; xconf.addr.s_addr |= addr; } // adapter mtu xconf.vmtu = 1500; if( config.get_number( "network-mtu-size", &numb ) ) xconf.vmtu = numb; } // enable wins options if( config.get_number( "client-wins-used", &numb ) ) { if( numb ) { // netbios name server address numb = 0; config.get_number( "client-wins-auto", &numb ); if( numb ) { // auto server configuration xconf.rqst |= IPSEC_OPTS_NBNS; } else { // static server configuration for( long index = 0; index < IPSEC_NBNS_MAX; index++ ) { if( !config.get_string( "client-wins-addr", text, MAX_CONFSTRING, index ) ) break; xconf.nscfg.nbns_list[ index ].s_addr = inet_addr( text ); xconf.nscfg.nbns_count++; } if( !xconf.nscfg.nbns_count ) { log( STATUS_FAIL, "config error : client-wins-addr undefined\n" ); return false; } xconf.opts |= IPSEC_OPTS_NBNS; } } } // enable dns options if( config.get_number( "client-dns-used", &numb ) ) { if( numb ) { numb = 0; config.get_number( "client-dns-auto", &numb ); if( numb ) { // auto server configuration xconf.rqst |= IPSEC_OPTS_DNSS; } else { // dns server addresses for( long index = 0; index < IPSEC_DNSS_MAX; index++ ) { if( !config.get_string( "client-dns-addr", text, MAX_CONFSTRING, index ) ) break; xconf.nscfg.dnss_list[ index ].s_addr = inet_addr( text ); xconf.nscfg.dnss_count++; } if( !xconf.nscfg.dnss_count ) { log( STATUS_FAIL, "config error : client-dns-addr undefined\n" ); return false; } xconf.opts |= IPSEC_OPTS_DNSS; } numb = 0; config.get_number( "client-dns-suffix-auto", &numb ); if( numb ) { // auto domain configuration xconf.rqst |= IPSEC_OPTS_DOMAIN; } else { // static domain configuration if( config.get_string( "client-dns-suffix", text, MAX_CONFSTRING, 0 ) ) { strncpy_s( xconf.nscfg.dnss_suffix, text, CONF_STRLEN ); xconf.opts |= IPSEC_OPTS_DOMAIN; } } } } // policy type peer.plcy_level = POLICY_LEVEL_AUTO; if( config.get_string( "policy-level", text, MAX_CONFSTRING, 0 ) ) { if( !strcmp( "use", text ) ) peer.plcy_level = POLICY_LEVEL_USE; if( !strcmp( "require", text ) ) peer.plcy_level = POLICY_LEVEL_REQUIRE; if( !strcmp( "unique", text ) ) peer.plcy_level = POLICY_LEVEL_UNIQUE; if( !strcmp( "shared", text ) ) peer.plcy_level = POLICY_LEVEL_SHARED; } // nailed policy enable numb = 0; config.get_number( "policy-nailed", &numb ); if( numb ) peer.nailed = true; // auto policy enable numb = 0; config.get_number( "policy-list-auto", &numb ); if( numb ) { // automatic policy config xconf.rqst |= IPSEC_OPTS_SPLITNET; } else { // static policy config xconf.opts |= IPSEC_OPTS_SPLITNET; } // vendor compatibility options numb = 0; config.get_number( "vendor-chkpt-enable", &numb ); if( numb ) xconf.opts |= IPSEC_OPTS_VEND_CHKPT; // // ---------- CONNECT TO IKED ---------- // long result; long msgres; if( ikei.attach( 3000 ) != IPCERR_OK ) { log( STATUS_FAIL, "failed to attach to key daemon\n" ); return false; } log( STATUS_INFO, "attached to key daemon ...\n" ); // // send the peer configuration message // IKEI_MSG msg; msg.set_peer( &peer ); result = ikei.send_message( msg, &msgres ); if( ( result != IPCERR_OK ) || ( msgres != IKEI_RESULT_OK ) ) { log( STATUS_FAIL, "peer config failed\n" ); goto config_failed; } log( STATUS_INFO, "peer configured\n" ); // // send proposal config messages // msg.set_proposal( &proposal_isakmp ); result = ikei.send_message( msg, &msgres ); if( ( result != IPCERR_OK ) || ( msgres != IKEI_RESULT_OK ) ) { log( STATUS_FAIL, "isakmp proposal config failed\n" ); goto config_failed; } log( STATUS_INFO, "iskamp proposal configured\n" ); msg.set_proposal( &proposal_esp ); result = ikei.send_message( msg, &msgres ); if( ( result != IPCERR_OK ) || ( msgres != IKEI_RESULT_OK ) ) { log( STATUS_FAIL, "esp proposal config failed\n" ); goto config_failed; } log( STATUS_INFO, "esp proposal configured\n" ); if( proposal_ipcomp.xform ) { msg.set_proposal( &proposal_ipcomp ); result = ikei.send_message( msg, &msgres ); if( ( result != IPCERR_OK ) || ( msgres != IKEI_RESULT_OK ) ) { log( STATUS_FAIL, "ipcomp proposal config failed\n" ); goto config_failed; } log( STATUS_INFO, "ipcomp proposal configured\n" ); } // // send the client configuration message // msg.set_client( &xconf ); result = ikei.send_message( msg, &msgres ); if( ( result != IPCERR_OK ) || ( msgres != IKEI_RESULT_OK ) ) { log( STATUS_FAIL, "client config failed\n" ); goto config_failed; } log( STATUS_INFO, "client configured\n" ); // // verify and send our xauth info // if( ( proposal_isakmp.auth_id == XAUTH_AUTH_INIT_PSK ) || ( proposal_isakmp.auth_id == XAUTH_AUTH_INIT_RSA ) || ( proposal_isakmp.auth_id == HYBRID_AUTH_INIT_RSA ) ) { get_username(); msg.set_cfgstr( CFGSTR_CRED_XAUTH_USER, &username ); result = ikei.send_message( msg, &msgres ); if( ( result != IPCERR_OK ) || ( msgres != IKEI_RESULT_OK ) ) { log( STATUS_FAIL, "xauth username config failed\n" ); goto config_failed; } get_password(); msg.set_cfgstr( CFGSTR_CRED_XAUTH_PASS, &password ); result = ikei.send_message( msg, &msgres ); if( ( result != IPCERR_OK ) || ( msgres != IKEI_RESULT_OK ) ) { log( STATUS_FAIL, "xauth password config failed\n" ); goto config_failed; } } // // verify and send our identity info // // client id data if( config.get_string( "ident-client-data", btext, 0 ) ) { msg.set_cfgstr( CFGSTR_CRED_LID, &btext ); result = ikei.send_message( msg, &msgres ); if( ( result != IPCERR_OK ) || ( msgres != IKEI_RESULT_OK ) ) { log( STATUS_FAIL, "local id config failed\n" ); goto config_failed; } } log( STATUS_INFO, "local id configured\n" ); // server id data if( config.get_string( "ident-server-data", btext, 0 ) ) { msg.set_cfgstr( CFGSTR_CRED_RID, &btext ); result = ikei.send_message( msg, &msgres ); if( ( result != IPCERR_OK ) || ( msgres != IKEI_RESULT_OK ) ) { log( STATUS_FAIL, "remote id config failed\n" ); goto config_failed; } } log( STATUS_INFO, "remote id configured\n" ); // // verify and send our peer authentication info // if( ( proposal_isakmp.auth_id == HYBRID_AUTH_INIT_RSA ) || ( proposal_isakmp.auth_id == XAUTH_AUTH_INIT_RSA ) || ( proposal_isakmp.auth_id == IKE_AUTH_SIG_RSA ) ) { BDATA name; // server certificate if( !config.get_string( "auth-server-cert-name", name, 0 ) ) { log( STATUS_FAIL, "config error : auth-server-cert-name undefined\n" ); goto config_failed; } if( !config.get_binary( "auth-server-cert-data", btext ) ) { log( STATUS_FAIL, "config error : auth-server-cert-data undefined\n" ); goto config_failed; } server_cert_rety: msg.set_cfgstr( CFGSTR_CRED_RSA_RCRT, &btext ); result = ikei.send_message( msg, &msgres ); if( ( result != IPCERR_OK ) || ( msgres == IKEI_RESULT_FAILED ) ) { log( STATUS_FAIL, "server cert config failed\n" ); goto config_failed; } if( msgres == IKEI_RESULT_PASSWD ) { if( !get_filepass( name ) ) { log( STATUS_FAIL, "server cert file requires password\n" ); goto config_failed; } msg.set_cfgstr( CFGSTR_CRED_FILE_PASS, &fpass ); result = ikei.send_message( msg, &msgres ); goto server_cert_rety; } log( STATUS_INFO, "server cert configured\n" ); } if( ( proposal_isakmp.auth_id == XAUTH_AUTH_INIT_RSA ) || ( proposal_isakmp.auth_id == IKE_AUTH_SIG_RSA ) ) { BDATA name; // client certificate if( !config.get_string( "auth-client-cert-name", name, 0 ) ) { log( STATUS_FAIL, "config error : auth-client-cert-name undefined\n" ); goto config_failed; } if( !config.get_binary( "auth-client-cert-data", btext ) ) { log( STATUS_FAIL, "config error : auth-client-cert-data undefined\n" ); goto config_failed; } client_cert_rety: msg.set_cfgstr( CFGSTR_CRED_RSA_LCRT, &btext ); result = ikei.send_message( msg, &msgres ); if( ( result != IPCERR_OK ) || ( msgres == IKEI_RESULT_FAILED ) ) { log( STATUS_FAIL, "client cert config failed\n" ); goto config_failed; } if( msgres == IKEI_RESULT_PASSWD ) { if( !get_filepass( name ) ) { log( STATUS_FAIL, "client cert file requires password\n" ); goto config_failed; } msg.set_cfgstr( CFGSTR_CRED_FILE_PASS, &fpass ); result = ikei.send_message( msg, &msgres ); goto client_cert_rety; } log( STATUS_INFO, "client cert configured\n" ); // client private key if( !config.get_string( "auth-client-cert-name", name, 0 ) ) { log( STATUS_FAIL, "config error : auth-client-cert-name undefined\n" ); goto config_failed; } if( !config.get_binary( "auth-client-key-data", btext ) ) { log( STATUS_FAIL, "config error : auth-client-key-data undefined\n" ); goto config_failed; } client_pkey_rety: msg.set_cfgstr( CFGSTR_CRED_RSA_LKEY, &btext ); result = ikei.send_message( msg, &msgres ); if( ( result != IPCERR_OK ) || ( msgres == IKEI_RESULT_FAILED ) ) { log( STATUS_FAIL, "client key config failed\n" ); goto config_failed; } if( msgres == IKEI_RESULT_PASSWD ) { if( !get_filepass( name ) ) { log( STATUS_FAIL, "client key file requires password\n" ); goto config_failed; } msg.set_cfgstr( CFGSTR_CRED_FILE_PASS, &fpass ); result = ikei.send_message( msg, &msgres ); goto client_pkey_rety; } log( STATUS_INFO, "client key configured\n" ); } if( ( proposal_isakmp.auth_id == XAUTH_AUTH_INIT_PSK ) || ( proposal_isakmp.auth_id == IKE_AUTH_PRESHARED_KEY ) || ( xconf.opts & IPSEC_OPTS_CISCO_GRP ) ) { // mutual preshared key BDATA psk; if( !config.get_binary( "auth-mutual-psk", psk ) ) { log( STATUS_FAIL, "config error : auth-mutual-psk undefined\n" ); goto config_failed; } msg.set_cfgstr( CFGSTR_CRED_PSK, &psk ); result = ikei.send_message( msg, &msgres ); if( ( result != IPCERR_OK ) || ( msgres == IKEI_RESULT_FAILED ) ) { log( STATUS_FAIL, "pre-shared key config failed\n" ); goto config_failed; } log( STATUS_INFO, "pre-shared key configured\n" ); } // // define our splitdns domains // if( ( xconf.opts & IPSEC_OPTS_SPLITDNS ) && !( xconf.rqst & IPSEC_OPTS_SPLITDNS ) ) { long index = 0; while( config.get_string( "client-splitdns-list", btext, index++ ) ) { msg.set_cfgstr( CFGSTR_SPLIT_DOMAIN, &btext ); result = ikei.send_message( msg, &msgres ); if( ( result != IPCERR_OK ) || ( msgres == IKEI_RESULT_FAILED ) ) { log( STATUS_FAIL, "split domain name config failed\n" ); goto config_failed; } } } // // define our manual remote id list // if( !( xconf.rqst & IPSEC_OPTS_SPLITNET ) ) { long index = 0; while( config.get_string( "policy-list-exclude", text, MAX_CONFSTRING, index ) ) { char * split = strchr( text, '/' ) + 2; unsigned long addr = inet_addr( text ); unsigned long mask = inet_addr( split ); IKE_PH2ID ph2id; memset( &ph2id, 0, sizeof( ph2id ) ); ph2id.type = ISAKMP_ID_IPV4_ADDR_SUBNET; ph2id.addr1.s_addr = addr; ph2id.addr2.s_addr = mask; msg.set_network( UNITY_SPLIT_EXCLUDE, &ph2id ); result = ikei.send_message( msg, &msgres ); if( ( result != IPCERR_OK ) || ( msgres == IKEI_RESULT_FAILED ) ) { log( STATUS_FAIL, "policy include config failed\n" ); goto config_failed; } index++; } index = 0; while( config.get_string( "policy-list-include", text, MAX_CONFSTRING, index ) ) { char * split = strchr( text, '/' ) + 2; unsigned long addr = inet_addr( text ); unsigned long mask = inet_addr( split ); IKE_PH2ID ph2id; memset( &ph2id, 0, sizeof( ph2id ) ); ph2id.type = ISAKMP_ID_IPV4_ADDR_SUBNET; ph2id.addr1.s_addr = addr; ph2id.addr2.s_addr = mask; msg.set_network( UNITY_SPLIT_INCLUDE, &ph2id ); result = ikei.send_message( msg, &msgres ); if( ( result != IPCERR_OK ) || ( msgres == IKEI_RESULT_FAILED ) ) { log( STATUS_FAIL, "policy include config failed\n" ); goto config_failed; } index++; } } // // ---------- ENABLE TUNNEL ---------- // msg.set_enable( true ); if( ikei.send_message( msg ) != IPCERR_OK ) { log( STATUS_FAIL, "send enable failed\n" ); goto config_failed; } // // no more user input past this point // connecting.alert(); return true; config_failed: ikei.detach(); log( STATUS_INFO, "detached from key daemon\n" ); return false; } bool _CLIENT::run_loop() { IKEI_MSG msg; // // ---------- FEEDBACK LOOP ---------- // long status; long result; BDATA btext; while( true ) { // // get the next message // result = ikei.recv_message( msg ); if( result == IPCERR_NODATA ) continue; if( ( result == IPCERR_FAILED ) || ( result == IPCERR_CLOSED ) ) { if( cstate != CLIENT_STATE_DISCONNECTED ) { log( STATUS_FAIL, "key daemon attachment error\n" ); cstate = CLIENT_STATE_DISCONNECTED; set_status( STATUS_DISCONNECTED, NULL ); } break; } // // check for user cancelation // if( result == IPCERR_WAKEUP ) { msg.set_enable( false ); if( ikei.send_message( msg ) != IPCERR_OK ) break; continue; } // // evaluate the message // switch( msg.header.type ) { // // status message // case IKEI_MSGID_STATUS: { if( msg.get_status( &status, &btext ) != IPCERR_OK ) break; switch( status ) { case STATUS_DISCONNECTED: cstate = CLIENT_STATE_DISCONNECTED; break; case STATUS_CONNECTING: cstate = CLIENT_STATE_CONNECTING; break; case STATUS_CONNECTED: cstate = CLIENT_STATE_CONNECTED; break; case STATUS_DISCONNECTING: cstate = CLIENT_STATE_DISCONNECTING; break; } set_status( status, &btext ); break; } // // statistics message // case IKEI_MSGID_STATS: { if( msg.get_stats( &stats ) != IPCERR_OK ) break; set_stats(); break; } } } ikei.detach(); log( STATUS_INFO, "detached from key daemon\n" ); return true; } long _CLIENT::func( void * arg ) { if( arg == ( void * ) 1 ) if( !run_init() ) return -1; if( !run_loop() ) return -1; return 0; } _CLIENT::_CLIENT() { memset( &stats, 0, sizeof( stats ) ); cstate = CLIENT_STATE_DISCONNECTED; autoconnect = false; suspended = false; } _CLIENT::~_CLIENT() { } CLIENT_STATE _CLIENT::state() { return cstate; } OPT_RESULT _CLIENT::read_opts( int argc, char ** argv ) { site_name.del(); // read our command line args bool syntax_error = false; for( int argi = 1; argi < argc; argi++ ) { // remote site name if( !strcmp( argv[ argi ], "-r" ) ) { if( ++argi >= argc ) return OPT_RESULT_SYNTAX_ERROR; site_name.set( argv[ argi ], strlen( argv[ argi ] ) + 1 ); continue; } #ifdef WIN32 if( !strcmp( argv[ argi ], "-s" ) ) { // this takes a few trys some times, // i have no idea why. we wait up to // 10 seconds for the file. int i = 0; for( ; i < 20; i++ ) { // read suspended site name from the // control file under windows temp char temp_path[ MAX_PATH ] = { 0 }; char file_path[ MAX_PATH ] = { 0 }; if( SHGetFolderPath( NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_DEFAULT, temp_path ) == S_OK ) { sprintf_s( file_path, "%s\\Shrew Soft VPN\\sscp-login-info", temp_path ); if( site_name.file_load( file_path ) ) { site_name.add( "", 1 ); DeleteFile( file_path ); break; } } Sleep( 500 ); } if( i >= 20 ) return OPT_RESULT_RESUME_ERROR; suspended = true; continue; } #endif // remote site username if( !strcmp( argv[ argi ], "-u" ) ) { if( ++argi >= argc ) return OPT_RESULT_SYNTAX_ERROR; username.set( argv[ argi ], strlen( argv[ argi ] ) ); continue; } // remote site password if( !strcmp( argv[ argi ], "-p" ) ) { if( ++argi >= argc ) return OPT_RESULT_SYNTAX_ERROR; password.set( argv[ argi ], strlen( argv[ argi ] ) ); continue; } // auto connect if( !strcmp( argv[ argi ], "-a" ) ) { autoconnect = true; continue; } // syntax error return OPT_RESULT_SYNTAX_ERROR; } // make sure we have a site name if( !site_name.size() ) return OPT_RESULT_SYNTAX_ERROR; return OPT_RESULT_SUCCESS; } void _CLIENT::show_help() { log( STATUS_FAIL, "invalid parameters specified ...\n" ); log( STATUS_INFO, "%s -r \"name\" [ -u ][ -p ][ -a ]\n" " -r\tsite configuration path\n" " -u\tconnection user name\n" " -p\tconnection user password\n" " -a\tauto connect\n", app_name() ); } bool _CLIENT::config_load() { if( !site_name.size() ) return false; config.set_id( site_name.text() ); bool loaded = manager.file_vpn_load( config ); if( !loaded ) { config.set_ispublic( true ); loaded = manager.file_vpn_load( config ); } if( !loaded ) { log( STATUS_FAIL, "failed to load \'%s\'\n", site_name.text() ); return false; } log( STATUS_INFO, "config loaded for site \'%s\'\n", site_name.text() ); return true; } bool _CLIENT::auto_connect() { return autoconnect; } bool _CLIENT::user_credentials() { char text[ MAX_CONFSTRING ]; if( config.get_string( "auth-method", text, MAX_CONFSTRING, 0 ) ) if( !strcmp( "hybrid-rsa-xauth", text ) || !strcmp( "hybrid-grp-xauth", text ) || !strcmp( "mutual-rsa-xauth", text ) || !strcmp( "mutual-psk-xauth", text ) ) return true; return false; } bool _CLIENT::vpn_connect( bool wait_input ) { if( cstate != CLIENT_STATE_DISCONNECTED ) { log( STATUS_FAIL, "tunnel connected! try disconnecting first\n" ); return false; } if( config.get_id() == NULL ) { log( STATUS_FAIL, "no site configuration loaded\n" ); return false; } connecting.reset(); exec( ( void * ) 1 ); if( wait_input ) connecting.wait( -1 ); return true; } bool _CLIENT::vpn_disconnect() { if( cstate == CLIENT_STATE_DISCONNECTED ) { log( STATUS_FAIL, "tunnel disconnected! try connecting first\n" ); return false; } if( config.get_id() == NULL ) { log( STATUS_FAIL, "no site configuration loaded\n" ); return false; } ikei.wakeup(); return true; } bool _CLIENT::vpn_suspend() { IKEI_MSG msg; msg.set_suspend( 1 ); if( ikei.send_message( msg ) != IPCERR_OK ) return false; return true; } bool _CLIENT::vpn_resume() { if( ikei.attach( 3000 ) != IPCERR_OK ) { log( STATUS_FAIL, "failed to attach to key daemon\n" ); return false; } log( STATUS_INFO, "attached to key daemon ...\n" ); IKEI_MSG msg; msg.set_suspend( 0 ); if( ikei.send_message( msg ) != IPCERR_OK ) { log( STATUS_INFO, "failed to resume vpn connection\n" ); return false; } cstate = CLIENT_STATE_CONNECTED; set_status( STATUS_CONNECTED, NULL ); exec( ( void * ) 0 ); return true; } ike-2.2.1+dfsg/source/libike/client.h000066400000000000000000000076121223036517100173770ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #ifndef _CLIENT_H_ #define _CLIENT_H_ #ifdef WIN32 # include # include # include #else # include # include # include # include #endif # include #include "libike.h" #include "config.h" #include "export.h" #include "version.h" enum OPT_RESULT { OPT_RESULT_SUCCESS, OPT_RESULT_SYNTAX_ERROR, OPT_RESULT_RESUME_ERROR }; enum CLIENT_STATE { CLIENT_STATE_DISCONNECTED, CLIENT_STATE_CONNECTING, CLIENT_STATE_CONNECTED, CLIENT_STATE_DISCONNECTING }; typedef class DLX _CLIENT : public ITH_EXEC { protected: ITH_COND connecting; CONFIG_MANAGER manager; BDATA site_name; IKE_PEER peer; IKE_XCONF xconf; IKE_PROPOSAL proposal_isakmp; IKE_PROPOSAL proposal_esp; IKE_PROPOSAL proposal_ipcomp; IKEI ikei; IKEI_STATS stats; BDATA fpath; BDATA fpass; BDATA username; BDATA password; bool autoconnect; bool suspended; virtual const char * app_name() = 0; virtual bool get_username() = 0; virtual bool get_password() = 0; virtual bool get_filepass( BDATA & path ) = 0; virtual bool set_stats() = 0; virtual bool set_status( long status, BDATA * text ) = 0; bool run_init(); bool run_loop(); long func( void * ); CONFIG config; CLIENT_STATE cstate; public: _CLIENT(); virtual ~_CLIENT(); OPT_RESULT read_opts( int argc, char ** argv ); void show_help(); bool config_load(); bool config_save(); CLIENT_STATE state(); bool auto_connect(); bool user_credentials(); bool vpn_connect( bool wait_input ); bool vpn_disconnect(); bool vpn_suspend(); bool vpn_resume(); virtual bool log( long code, const char * format, ... ) = 0; }CLIENT; #endif ike-2.2.1+dfsg/source/libike/config.cpp000066400000000000000000000212421223036517100177140ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "config.h" #define DELIM_NEW ',' #define DELIM_OLD 0x255 inline const char * text_delim( const char * text ) { const char * delim; delim = strchr( text, DELIM_NEW ); if( delim == NULL ) delim = strchr( text, DELIM_OLD ); return delim; } inline size_t text_length( const char * text ) { size_t oset = 0; while( true ) { int c = text[ oset ]; switch( c ) { case 0: case DELIM_OLD: case DELIM_NEW: return oset; default: oset++; } } return 0; } /* * CONFIG class member functions */ _CFGDAT::_CFGDAT() { nval = 0; } _CONFIG::_CONFIG() { ispublic = false; } _CONFIG::~_CONFIG() { } bool _CONFIG::set_id( const char * set_id ) { id.del(); id.set( set_id, strlen( set_id ) + 1 ); return true; } char * _CONFIG::get_id() { return id.text(); } void _CONFIG::set_ispublic( bool val ) { ispublic = val; } bool _CONFIG::get_ispublic() { return ispublic; } _CONFIG & _CONFIG::operator = ( _CONFIG & config ) { del_all(); set_id( config.get_id() ); set_ispublic( config.get_ispublic() ); for( long index = 0; index < config.count(); index++ ) { CFGDAT * cfgdat = static_cast( config.get_entry( index ) ); switch( cfgdat->type ) { case DATA_STRING: set_string( cfgdat->key.text(), cfgdat->vval.text(), cfgdat->vval.size() ); break; case DATA_NUMBER: set_number( cfgdat->key.text(), cfgdat->nval ); break; case DATA_BINARY: set_binary( cfgdat->key.text(), cfgdat->vval ); break; } } return *this; } CFGDAT * _CONFIG::get_data( long type, const char * key, bool add ) { CFGDAT * cfgdat; for( long index = 0; index < count(); index++ ) { cfgdat = static_cast( get_entry( index ) ); if( cfgdat->type != type ) continue; if( !_stricmp( cfgdat->key.text(), key ) ) return cfgdat; } if( add ) { cfgdat = new CFGDAT; if( cfgdat == NULL ) return NULL; cfgdat->type = type; cfgdat->key.set( key, strlen( key ) + 1 ); add_entry( cfgdat ); return cfgdat; } return NULL; } void _CONFIG::del( const char * key ) { CFGDAT * cfgdat; for( long index = 0; index < count(); index++ ) { cfgdat = static_cast( get_entry( index ) ); if( !_stricmp( cfgdat->key.text(), key ) ) { del_entry( cfgdat ); delete cfgdat; } } } void _CONFIG::del_all() { clean(); } bool _CONFIG::add_string( const char * key, const char * val, size_t size ) { CFGDAT * cfgdat = get_data( DATA_STRING, key, true ); if( !cfgdat ) return false; if( cfgdat->vval.size() ) { cfgdat->vval.set( ",", 1, cfgdat->vval.size() - 1 ); cfgdat->vval.add( val, size ); cfgdat->vval.add( "", 1 ); } else { cfgdat->vval.add( val, size ); cfgdat->vval.add( "", 1 ); } return true; } bool _CONFIG::add_string( const char * key, BDATA & val ) { CFGDAT * cfgdat = get_data( DATA_STRING, key, true ); if( !cfgdat ) return false; if( cfgdat->vval.size() ) { cfgdat->vval.set( ",", 1, cfgdat->vval.size() - 1 ); cfgdat->vval.add( val ); cfgdat->vval.add( "", 1 ); } else { cfgdat->vval.add( val ); cfgdat->vval.add( "", 1 ); } return true; } bool _CONFIG::set_string( const char * key, const char * val, size_t size ) { del( key ); add_string( key, val, size ); return true; } bool _CONFIG::set_string( const char * key, BDATA & val ) { del( key ); add_string( key, val ); return true; } long _CONFIG::has_string( const char * key, const char * val, size_t size ) { CFGDAT * cfgdat = get_data( DATA_STRING, key ); if( !cfgdat ) return -1; const char * oldptr = cfgdat->vval.text(); const char * newptr = cfgdat->vval.text(); long index = 0; while( newptr ) { newptr = text_delim( oldptr ); if( newptr ) { size_t diff = newptr - oldptr; if( diff < size ) size = diff; } if( !strncmp( val, oldptr, size ) ) return index; oldptr = newptr + 1; index++; } return -1; } bool _CONFIG::get_string( const char * key, char * val, size_t size, int index ) { CFGDAT * cfgdat = get_data( DATA_STRING, key ); if( !cfgdat ) return false; const char * strptr = cfgdat->vval.text(); for( ; index > 0; index-- ) { const char * tmpptr = text_delim( strptr ); if( tmpptr == NULL ) return false; strptr = tmpptr + 1; } // calculate final length size--; size_t clen = text_length( strptr ); if( clen < size ) size = clen; memcpy( val, strptr, size ); val[ size ] = 0; return true; } bool _CONFIG::get_string( const char * key, BDATA & val, int index ) { CFGDAT * cfgdat = get_data( DATA_STRING, key ); if( !cfgdat ) return false; const char * strptr = cfgdat->vval.text(); for( ; index > 0; index-- ) { const char * tmpptr = text_delim( strptr ); if( tmpptr == NULL ) return false; strptr = tmpptr + 1; } // calculate final length size_t clen = text_length( strptr ); val.del(); val.set( strptr, clen ); return true; } bool _CONFIG::set_number( const char * key, long val ) { CFGDAT * cfgdat = get_data( DATA_NUMBER, key, true ); if( !cfgdat ) return false; cfgdat->nval = val; return true; } bool _CONFIG::get_number( const char * key, long * val ) { CFGDAT * cfgdat = get_data( DATA_NUMBER, key ); if( !cfgdat ) return false; *val = cfgdat->nval; return true; } bool _CONFIG::set_binary( const char * key, BDATA & val ) { CFGDAT * cfgdat = get_data( DATA_BINARY, key, true ); if( !cfgdat ) return false; cfgdat->vval = val; return true; } bool _CONFIG::get_binary( const char * key, BDATA & val ) { CFGDAT * cfgdat = get_data( DATA_BINARY, key ); if( !cfgdat ) return false; val = cfgdat->vval; return true; } bool config_cmp_number( CONFIG * config_old, CONFIG * config_new, const char * key ) { if( !config_old ) return false; long number1; long number2; if( config_old->get_number( key, &number1 ) && config_new->get_number( key, &number2 ) ) if( number1 != number2 ) return false; return true; } bool config_cmp_string( CONFIG * config_old, CONFIG * config_new, const char * key ) { if( !config_old ) return false; char string1[ MAX_CONFSTRING + 1 ]; char string2[ MAX_CONFSTRING + 1 ]; if( config_old->get_string( key, string1, MAX_CONFSTRING, 0 ) && config_new->get_string( key, string2, MAX_CONFSTRING, 0 ) ) if( strcmp( string1, string2 ) ) return false; return true; } ike-2.2.1+dfsg/source/libike/config.h000066400000000000000000000123661223036517100173700ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #ifndef _CONFIG_H_ #define _CONFIG_H_ #ifdef WIN32 # include # include # include # include #endif #ifdef UNIX # ifdef __linux__ # include # include # else # include # include # include # endif # include # include # include # include //# include # include "compat/winstring.h" #endif #include #include #include "libidb.h" #ifdef WIN32 # define PATH_DELIM '\\' #else # define PATH_DELIM '/' #endif #define MAX_CONFSTRING 256 #define CONFIG_VERSION 4 #define DATA_STRING 1 #define DATA_NUMBER 2 #define DATA_BINARY 3 #define CONFIG_OK 0 #define CONFIG_FAILED 1 #define CONFIG_CANCEL 2 typedef class _CFGDAT : public IDB_ENTRY { public: BDATA key; long type; BDATA vval; long nval; _CFGDAT(); }CFGDAT; typedef class DLX _CONFIG : public IDB_LIST { protected: BDATA id; bool ispublic; CFGDAT * get_data( long type, const char * key, bool add = false ); public: _CONFIG(); ~_CONFIG(); _CONFIG & operator = ( _CONFIG & value ); bool set_id( const char * id ); char * get_id(); void set_ispublic( bool val ); bool get_ispublic(); void del( const char * key ); void del_all(); bool add_string( const char * key, const char * val, size_t size ); bool add_string( const char * key, BDATA & val ); bool set_string( const char * key, const char * val, size_t size ); bool set_string( const char * key, BDATA & val ); bool get_string( const char * key, char * val, size_t size, int index ); bool get_string( const char * key, BDATA & val, int index ); long has_string( const char * key, const char * val, size_t size ); bool set_number( const char * key, long val ); bool get_number( const char * key, long * val ); bool set_binary( const char * key, BDATA & val ); bool get_binary( const char * key, BDATA & val ); }CONFIG; typedef class DLX _CONFIG_MANAGER { protected: BDATA sites_all; BDATA certs_all; BDATA sites_user; BDATA certs_user; bool update_config( CONFIG & config ); public: _CONFIG_MANAGER(); bool config_options_load(); bool file_enumerate( CONFIG & config, int & index ); bool file_enumerate_public( CONFIG & config, int & index ); bool file_vpn_load( CONFIG & config ); bool file_vpn_load( CONFIG & config, const char * path, bool save_update = true ); bool file_vpn_save( CONFIG & config ); bool file_vpn_save( CONFIG & config, const char * path ); bool file_vpn_del( CONFIG & config ); bool file_pcf_load( CONFIG & config, const char * path, bool & need_certs ); #ifdef WIN32 bool registry_enumerate( CONFIG & config, int & index ); bool registry_vpn_load( CONFIG & config ); bool registry_vpn_save( CONFIG & config ); bool registry_vpn_del( CONFIG & config ); #endif }CONFIG_MANAGER; bool config_cmp_number( CONFIG & config_old, CONFIG & config_new, const char * key ); bool config_cmp_string( CONFIG & config_old, CONFIG & config_new, const char * key ); #endif ike-2.2.1+dfsg/source/libike/libike.cpp000066400000000000000000000174431223036517100177160ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "libike.h" void _IKEI_MSG::init( long type ) { del(); header.type = type; } long _IKEI_MSG::get_basic( long * value, BDATA * bdata ) { IKEI_BASIC basic; if( !get( &basic, sizeof( basic ) ) ) return IPCERR_FAILED; if( value != NULL ) *value = basic.value; if( bdata != NULL ) if( !get( *bdata, basic.bsize ) ) return IPCERR_FAILED; return IPCERR_OK; } long _IKEI_MSG::set_basic( long value, BDATA * bdata ) { IKEI_BASIC basic; basic.value = value; if( bdata != NULL ) basic.bsize = bdata->size(); else basic.bsize = 0; if( !add( &basic, sizeof( basic ) ) ) return IPCERR_FAILED; if( bdata != NULL ) if( !add( *bdata ) ) return IPCERR_FAILED; return IPCERR_OK; } long _IKEI_MSG::get_struct( long * value, void * sdata, size_t ssize ) { IKEI_BASIC basic; if( !get( &basic, sizeof( basic ) ) ) return IPCERR_FAILED; if( value != NULL ) *value = basic.value; if( sdata != NULL ) if( !get( sdata, ssize ) ) return IPCERR_FAILED; return IPCERR_OK; } long _IKEI_MSG::set_struct( long value, void * sdata, size_t ssize ) { IKEI_BASIC basic; basic.value = value; if( sdata != NULL ) basic.bsize = ssize; else basic.bsize = 0; if( !add( &basic, sizeof( basic ) ) ) return IPCERR_FAILED; if( sdata != NULL ) if( !add( sdata, ssize ) ) return IPCERR_FAILED; return IPCERR_OK; } long _IKEI_MSG::get_result( long * msgres ) { return get_basic( msgres ); } long _IKEI_MSG::set_result( long msgres ) { init( IKEI_MSGID_RESULT ); return set_basic( msgres ); } long _IKEI_MSG::get_status( long * status, BDATA * str ) { return get_basic( status, str ); } long _IKEI_MSG::set_status( long status, BDATA * str ) { init( IKEI_MSGID_STATUS ); return set_basic( status, str ); } long _IKEI_MSG::set_status( long status, const char * str ) { BDATA text; text.set( str, strlen( str ) + 1 ); return set_status( status, &text ); } long _IKEI_MSG::get_stats( IKEI_STATS * stats ) { return get_struct( 0, stats, sizeof( IKEI_STATS ) ); } long _IKEI_MSG::set_stats( IKEI_STATS * stats ) { init( IKEI_MSGID_STATS ); return set_struct( 0, stats, sizeof( IKEI_STATS ) ); } long _IKEI_MSG::get_enable( long * enable ) { return get_basic( enable ); } long _IKEI_MSG::set_enable( long enable ) { init( IKEI_MSGID_ENABLE ); return set_basic( enable ); } long _IKEI_MSG::get_suspend( long * suspend ) { return get_basic( suspend ); } long _IKEI_MSG::set_suspend( long suspend ) { init( IKEI_MSGID_SUSPEND ); return set_basic( suspend ); } long _IKEI_MSG::get_peer( IKE_PEER * peer ) { return get_struct( 0, peer, sizeof( IKE_PEER ) ); } long _IKEI_MSG::set_peer( IKE_PEER * peer ) { init( IKEI_MSGID_PEER ); return set_struct( 0, peer, sizeof( IKE_PEER ) ); } long _IKEI_MSG::get_proposal( IKE_PROPOSAL * proposal ) { return get_struct( 0, proposal, sizeof( IKE_PROPOSAL ) ); } long _IKEI_MSG::set_proposal( IKE_PROPOSAL * proposal ) { init( IKEI_MSGID_PROPOSAL ); return set_struct( 0, proposal, sizeof( IKE_PROPOSAL ) ); } long _IKEI_MSG::get_client( IKE_XCONF * xconf ) { return get_struct( 0, xconf, sizeof( IKE_XCONF ) ); } long _IKEI_MSG::set_client( IKE_XCONF * xconf ) { init( IKEI_MSGID_CLIENT ); return set_struct( 0, xconf, sizeof( IKE_XCONF ) ); } long _IKEI_MSG::get_network( long * type, IKE_PH2ID * ph2id ) { return get_struct( type, ph2id, sizeof( IKE_PH2ID ) ); } long _IKEI_MSG::set_network( long type, IKE_PH2ID * ph2id ) { init( IKEI_MSGID_NETWORK ); return set_struct( type, ph2id, sizeof( IKE_PH2ID ) ); } long _IKEI_MSG::get_cfgstr( long * type, BDATA * str ) { return get_basic( type, str ); } long _IKEI_MSG::set_cfgstr( long type, BDATA * str ) { init( IKEI_MSGID_CFGSTR ); return set_basic( type, str ); } long _IKEI::attach( long timeout ) { return ITH_IPCC::attach( IKEI_PIPE_NAME, timeout ); } void _IKEI::wakeup() { ITH_IPCC::wakeup(); } void _IKEI::detach() { ITH_IPCC::detach(); } long _IKEI::recv_message( IKEI_MSG & msg ) { msg.oset( 0 ); msg.size( sizeof( IKEI_HEADER ) ); size_t size = msg.size(); long result = io_recv( msg.buff(), size ); if( ( result == IPCERR_OK ) || ( result == IPCERR_BUFFER ) ) { msg.oset( 0 ); if( !msg.get( &msg.header, sizeof( IKEI_HEADER ) ) ) return IPCERR_FAILED; if( msg.header.size > msg.size() ) result = IPCERR_BUFFER; } if( result == IPCERR_BUFFER ) { msg.size( msg.header.size ); if( msg.size() < msg.header.size ) return IPCERR_FAILED; size = msg.size() - sizeof( IKEI_HEADER ); result = io_recv( msg.buff() + sizeof( IKEI_HEADER ), size ); } return result; } long _IKEI::send_message( IKEI_MSG & msg ) { msg.header.size = msg.size() + sizeof( msg.header ); msg.ins( &msg.header, sizeof( msg.header ) ); return io_send( msg.buff(), msg.header.size ); } long _IKEI::send_message( IKEI_MSG & msg, long * rslt ) { long result; result = send_message( msg ); if( result != IPCERR_OK ) return result; IKEI_MSG msg_rslt; result = recv_message( msg_rslt ); if( result != IPCERR_OK ) return result; return msg_rslt.get_result( rslt ); } long _IKES::init() { return ITH_IPCS::init( IKEI_PIPE_NAME, false ); } void _IKES::done() { ITH_IPCS::done(); } long _IKES::inbound( IKEI ** ikei ) { IPCCONN ipcconn; long result = ITH_IPCS::inbound( IKEI_PIPE_NAME, ipcconn ); if( result == IPCERR_OK ) { *ikei = new IKEI; if( *ikei == NULL ) return IPCERR_FAILED; (*ikei)->io_conf( ipcconn ); } return result; } void _IKES::wakeup() { ITH_IPCS::wakeup(); } ike-2.2.1+dfsg/source/libike/libike.h000066400000000000000000000132771223036517100173640ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #ifndef _LIBIKED_H_ #define _LIBIKED_H_ #ifdef WIN32 # include # include #endif #ifdef UNIX # include # include # include # ifdef __linux__ # include # include # else # include # include # include # endif #endif #include #include #include #include "libidb.h" #include "libith.h" #include "ike.h" #include "export.h" #ifdef WIN32 # define IKEI_PIPE_NAME "\\\\.\\pipe\\ikedi" #else # define IKEI_PIPE_NAME "/var/run/ikedi" #endif #define IKEI_MSGID_RESULT 1 #define IKEI_MSGID_ENABLE 2 #define IKEI_MSGID_SUSPEND 3 #define IKEI_MSGID_STATUS 4 #define IKEI_MSGID_PEER 5 #define IKEI_MSGID_PROPOSAL 6 #define IKEI_MSGID_CLIENT 7 #define IKEI_MSGID_NETWORK 8 #define IKEI_MSGID_CFGSTR 9 #define IKEI_MSGID_STATS 10 #define IKEI_RESULT_OK 0 #define IKEI_RESULT_FAILED 1 #define IKEI_RESULT_PASSWD 2 #define CFGSTR_CRED_XAUTH_USER 1 #define CFGSTR_CRED_XAUTH_PASS 2 #define CFGSTR_CRED_FILE_PASS 3 #define CFGSTR_CRED_PSK 4 #define CFGSTR_CRED_RSA_LKEY 5 #define CFGSTR_CRED_RSA_LCRT 6 #define CFGSTR_CRED_RSA_RCRT 7 #define CFGSTR_CRED_LID 8 #define CFGSTR_CRED_RID 9 #define CFGSTR_SPLIT_DOMAIN 10 #define STATUS_DISCONNECTED 1 #define STATUS_CONNECTING 2 #define STATUS_CONNECTED 3 #define STATUS_DISCONNECTING 4 #define STATUS_BANNER 5 #define STATUS_INFO 6 #define STATUS_WARN 7 #define STATUS_FAIL 8 typedef struct _IKEI_HEADER { long type; size_t size; }IKEI_HEADER; typedef struct _IKEI_BASIC { long value; size_t bsize; }IKEI_BASIC; typedef struct _IKEI_STATS { IKE_SADDR peer; long sa_good; long sa_fail; long sa_dead; long natt; bool frag; bool dpd; }IKEI_STATS; typedef class DLX _IKEI_MSG : public BDATA { private: void init( long type ); long get_basic( long * value, BDATA * bdata = NULL ); long set_basic( long value, BDATA * bdata = NULL ); long get_struct( long * value, void * sdata, size_t ssize ); long set_struct( long value, void * sdata, size_t ssize ); public: IKEI_HEADER header; long get_result( long * msgres ); long set_result( long msgres ); long get_status( long * status, BDATA * str ); long set_status( long status, BDATA * str ); long set_status( long status, const char * str ); long get_stats( IKEI_STATS * stats ); long set_stats( IKEI_STATS * stats ); long get_enable( long * enable ); long set_enable( long enable ); long get_suspend( long * suspend ); long set_suspend( long suspend ); long get_peer( IKE_PEER * peer ); long set_peer( IKE_PEER * peer ); long get_proposal( IKE_PROPOSAL * proposal ); long set_proposal( IKE_PROPOSAL * proposal ); long get_client( IKE_XCONF * xconf ); long set_client( IKE_XCONF * xconf ); long get_network( long * type, IKE_PH2ID * ph2id ); long set_network( long type, IKE_PH2ID * ph2id ); long get_cfgstr( long * type, BDATA * str ); long set_cfgstr( long type, BDATA * str ); }IKEI_MSG; typedef class DLX _IKEI : private _ITH_IPCC { friend class _IKES; public: long attach( long timeout ); void wakeup(); void detach(); long recv_message( IKEI_MSG & msg ); long send_message( IKEI_MSG & msg ); long send_message( IKEI_MSG & msg, long * rslt ); }IKEI; typedef class DLX _IKES : private _ITH_IPCS { public: long init(); void done(); long inbound( IKEI ** ikei ); void wakeup(); }IKES; #endif ike-2.2.1+dfsg/source/libike/manager.cpp000066400000000000000000000216251223036517100200660ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "config.h" bool file_to_name( BDATA & path, BDATA & name ) { name.del(); char * lastslash = strrchr( path.text(), PATH_DELIM ); if( lastslash == NULL ) name.set( path.text(), path.size() - 1 ); else name.set( lastslash + 1, strlen( lastslash + 1 ) ); return ( name.size() > 0 ); } bool _CONFIG_MANAGER::update_config( CONFIG & config ) { long version = 0; config.get_number( "version", &version ); if( version >= CONFIG_VERSION ) return false; while( version < CONFIG_VERSION ) { switch( version ) { case 0: // 0 -> 1 { // // update the auth-mutual-psk string // to a binary value // BDATA data; if( config.get_string( "auth-mutual-psk", data, 0 ) ) { data.size( data.size() - 1 ); config.set_binary( "auth-mutual-psk", data ); } break; } case 1: // 1 -> 2 { // // update client-dns-enable number to // client-dns-used // long numb; if( config.get_number( "client-dns-enable", &numb ) ) { config.del( "client-dns-enable" ); config.set_number( "client-dns-used", numb ); } break; } case 2: // 2 -> 3 { // // update client-dns-suffix-auto // long numb1 = 0; long numb2 = 1; BDATA data; if( config.get_number( "client-dns-used", &numb1 ) ) if( numb1 ) if( config.get_string( "client-dns-suffix", data, 0 ) ) numb2 = 0; config.set_number( "client-dns-suffix-auto", numb2 ); break; } case 3: // 3 -> 4 { // // update certificate name information // BDATA path; BDATA name; BDATA data; if( config.get_string( "auth-server-cert", path, 0 ) ) { if( !config.get_binary( "auth-server-cert-data", data ) ) { BDATA path2; path2.set( path ); path2.add( "", 1 ); file_to_name( path2, name ); data.file_load( path2.text() ); config.del( "auth-server-cert" ); config.set_string( "auth-server-cert-name", name ); config.set_binary( "auth-server-cert-data", data ); } else { config.del( "auth-server-cert" ); config.set_string( "auth-server-cert-name", path ); } } if( config.get_string( "auth-client-cert", path, 0 ) ) { if( !config.get_binary( "auth-client-cert-data", data ) ) { BDATA path2; path2.set( path ); path2.add( "", 1 ); file_to_name( path2, name ); data.file_load( path2.text() ); config.del( "auth-client-cert" ); config.set_string( "auth-client-cert-name", name ); config.set_binary( "auth-client-cert-data", data ); } else { config.del( "auth-client-cert" ); config.set_string( "auth-client-cert-name", path ); } } if( config.get_string( "auth-client-key", path, 0 ) ) { if( !config.get_binary( "auth-client-key-data", data ) ) { BDATA path2; path2.set( path ); path2.add( "", 1 ); file_to_name( path2, name ); data.file_load( path2.text() ); config.del( "auth-client-key" ); config.set_string( "auth-client-key-name", name ); config.set_binary( "auth-client-key-data", data ); } else { config.del( "auth-client-key" ); config.set_string( "auth-client-key-name", path ); } } break; } } version++; } // // update to current version // config.set_number( "version", CONFIG_VERSION ); return true; } _CONFIG_MANAGER::_CONFIG_MANAGER() { #ifdef WIN32 char path_appdata[ MAX_PATH ] = { 0 }; if( SHGetFolderPath( NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_DEFAULT, path_appdata ) == S_OK ) { char path_ssoft[] = "\\Shrew Soft VPN"; BDATA ssoft; ssoft.add( path_appdata, strlen( path_appdata ) ); ssoft.add( path_ssoft, strlen( path_ssoft ) + 1 ); if( !PathFileExists( ssoft.text() ) ) CreateDirectory( ssoft.text(), NULL ); char path_sites[] = "\\Shrew Soft VPN\\sites"; sites_all.add( path_appdata, strlen( path_appdata ) ); sites_all.add( path_sites, strlen( path_sites ) + 1 ); if( !PathFileExists( sites_all.text() ) ) CreateDirectory( sites_all.text(), NULL ); char path_certs[] = "\\Shrew Soft VPN\\certs"; certs_all.add( path_appdata, strlen( path_appdata ) ); certs_all.add( path_certs, strlen( path_certs ) + 1 ); if( !PathFileExists( certs_all.text() ) ) CreateDirectory( certs_all.text(), NULL ); } if( SHGetFolderPath( NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_DEFAULT, path_appdata ) == S_OK ) { char path_ssoft[] = "\\Shrew Soft VPN"; BDATA ssoft; ssoft.add( path_appdata, strlen( path_appdata ) ); ssoft.add( path_ssoft, strlen( path_ssoft ) + 1 ); if( !PathFileExists( ssoft.text() ) ) CreateDirectory( ssoft.text(), NULL ); char path_sites[] = "\\Shrew Soft VPN\\sites"; sites_user.add( path_appdata, strlen( path_appdata ) ); sites_user.add( path_sites, strlen( path_sites ) + 1 ); #ifndef OPT_DLLPROJ if( !PathFileExists( sites_user.text() ) ) { CreateDirectory( sites_user.text(), NULL ); // migrate sites from registry CONFIG config; int index = 0; while( registry_enumerate( config, index ) ) { file_vpn_save( config ); config.del_all(); } } #endif char path_certs[] = "\\Shrew Soft VPN\\certs"; certs_user.add( path_appdata, strlen( path_appdata ) ); certs_user.add( path_certs, strlen( path_certs ) + 1 ); if( !PathFileExists( certs_user.text() ) ) CreateDirectory( certs_user.text(), NULL ); } #else // locate user home directory struct passwd * pwd = getpwuid( getuid() ); if( pwd == NULL ) { printf( "unable to read pwent for %i\n", getuid() ); exit( -1 ); } // create .ike path char path_dotike[] = "/.ike"; BDATA dotike; dotike.add( pwd->pw_dir, strlen( pwd->pw_dir ) ); dotike.add( path_dotike, strlen( path_dotike ) + 1 ); struct stat sb; memset( &sb, 0, sizeof( sb ) ); if( stat( dotike.text(), &sb ) ) mkdir( dotike.text(), S_IRWXU ); // create sites path char path_sites[] = "/.ike/sites"; sites_user.add( pwd->pw_dir, strlen( pwd->pw_dir ) ); sites_user.add( path_sites, strlen( path_sites ) + 1 ); memset( &sb, 0, sizeof( sb ) ); if( stat( sites_user.text(), &sb ) ) mkdir( sites_user.text(), S_IRWXU ); // create certss path char path_certs[] = "/.ike/certs"; certs_user.add( pwd->pw_dir, strlen( pwd->pw_dir ) ); certs_user.add( path_certs, strlen( path_certs ) + 1 ); memset( &sb, 0, sizeof( sb ) ); if( stat( certs_user.text(), &sb ) ) mkdir( certs_user.text(), S_IRWXU ); endpwent(); #endif } ike-2.2.1+dfsg/source/libike/manager.file.cpp000066400000000000000000000360451223036517100210060ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "config.h" #include "openssl/rand.h" #include "openssl/hmac.h" #include "openssl/sha.h" bool _CONFIG_MANAGER::file_enumerate( CONFIG & config, int & index ) { #ifdef WIN32 BDATA sites_user_spec; sites_user_spec.add( sites_user ); sites_user_spec.ins( "\\*", 2, sites_user_spec.size() - 1 ); WIN32_FIND_DATA ffdata; int found = 0; HANDLE hfind = FindFirstFile( sites_user_spec.text(), &ffdata ); if( hfind == INVALID_HANDLE_VALUE ) return false; while( true ) { bool isdir = false; if( ffdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) isdir = true; if( !isdir && ( found >= ( index ) ) ) break; if( FindNextFile( hfind, &ffdata ) == 0 ) break; if( !isdir ) found++; } FindClose( hfind ); if( found < index ) return false; config.set_id( ffdata.cFileName ); index++; return file_vpn_load( config ); #else int found = 0; DIR * dirp = opendir( sites_user.text() ); if( dirp == NULL ) return false; dirent * dp = NULL; while( found <= index ) { dp = readdir( dirp ); if( dp == NULL ) break; if( dp->d_type & DT_DIR ) continue; found++; } closedir( dirp ); if( dp == NULL ) return false; config.set_id( dp->d_name ); index++; return file_vpn_load( config ); #endif } bool _CONFIG_MANAGER::file_enumerate_public( CONFIG & config, int & index ) { #ifdef WIN32 BDATA sites_user_spec; sites_user_spec.add( sites_all ); sites_user_spec.ins( "\\*", 2, sites_user_spec.size() - 1 ); WIN32_FIND_DATA ffdata; int found = 0; HANDLE hfind = FindFirstFile( sites_user_spec.text(), &ffdata ); if( hfind == INVALID_HANDLE_VALUE ) return false; while( true ) { bool isdir = false; if( ffdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) isdir = true; if( !isdir && ( found >= ( index ) ) ) break; if( FindNextFile( hfind, &ffdata ) == 0 ) break; if( !isdir ) found++; } FindClose( hfind ); if( found < index ) return false; config.set_id( ffdata.cFileName ); config.set_ispublic( true ); index++; return file_vpn_load( config ); #else return false; #endif } bool _CONFIG_MANAGER::file_vpn_load( CONFIG & config ) { BDATA path; if( config.get_ispublic() ) path.add( sites_all ); else path.add( sites_user ); path.ins( PATH_DELIM, 1, path.size() - 1 ); path.ins( config.get_id(), strlen( config.get_id() ), path.size() - 1 ); return file_vpn_load( config, path.text() ); } bool _CONFIG_MANAGER::file_vpn_load( CONFIG & config, const char * path, bool save_update ) { #ifdef WIN32 FILE * fp; if( fopen_s( &fp, path, "r" ) ) return false; #else FILE * fp = fopen( path, "r" ); if( fp == NULL ) return false; #endif while( true ) { char next; char type; BDATA name; BDATA data; // // get value type // type = fgetc( fp ); if( ( type == ' ' ) || ( type == '\r' ) ) continue; if( ( type == '\n' ) || ( type == EOF ) ) break; // // get delim // if( fgetc( fp ) != ':' ) goto parse_fail; // // get value name // while( true ) { next = fgetc( fp ); if( ( next == ':' ) || ( next == '\n' ) || ( next == EOF ) ) break; name.add( next, 1 ); } if( !name.size() ) goto parse_fail; name.add( "", 1 ); // // check delim // if( next != ':' ) goto parse_fail; // // get value data // while( true ) { next = fgetc( fp ); if( next == '\r' ) continue; if( ( next == '\n' ) || ( next == EOF ) ) break; data.add( next, 1 ); } data.add( "", 1 ); switch( type ) { case 's': { config.add_string( name.text(), data.text(), data.size() ); break; } case 'n': { config.set_number( name.text(), atol( data.text() ) ); break; } case 'b': { BDATA b64; b64 = data; b64.base64_decode(); config.set_binary( name.text(), b64 ); break; } } } fclose( fp ); // // automatically update configs // if( update_config( config ) && save_update ) file_vpn_save( config, path ); return true; parse_fail: fclose( fp ); return false; } bool _CONFIG_MANAGER::file_vpn_save( CONFIG & config ) { BDATA path; if( config.get_ispublic() ) path.add( sites_all ); else path.add( sites_user ); path.ins( "/", 1, path.size() - 1 ); path.ins( config.get_id(), strlen( config.get_id() ), path.size() - 1 ); return file_vpn_save( config, path.text() ); } bool _CONFIG_MANAGER::file_vpn_save( CONFIG & config, const char * path ) { #ifdef WIN32 FILE * fp; if( fopen_s( &fp, path, "w" ) ) return false; #else FILE * fp = fopen( path, "w" ); if( fp == NULL ) return false; #endif for( long index = 0; index < config.count(); index++ ) { CFGDAT * cfgdat = static_cast( config.get_entry( index ) ); switch( cfgdat->type ) { case DATA_STRING: fprintf( fp, "s:%s:%s\n", cfgdat->key.text(), cfgdat->vval.text() ); break; case DATA_NUMBER: fprintf( fp, "n:%s:%li\n", cfgdat->key.text(), cfgdat->nval ); break; case DATA_BINARY: { BDATA b64; b64 = cfgdat->vval; b64.base64_encode(); fprintf( fp, "b:%s:%s\n", cfgdat->key.text(), b64.text() ); break; } } } fclose( fp ); return true; } bool _CONFIG_MANAGER::file_vpn_del( CONFIG & config ) { BDATA path; if( config.get_ispublic() ) path.add( sites_all ); else path.add( sites_user ); path.ins( "/", 1, path.size() - 1 ); path.ins( config.get_id(), strlen( config.get_id() ), path.size() - 1 ); #ifdef WIN32 return ( DeleteFile( path.text() ) != 0 ); #else return ( unlink( path.text() ) == 0 ); #endif } bool read_line_pcf( FILE * fp, BDATA & name, BDATA & data ) { char next; BDATA line; name.del(); data.del(); // // read the next line // while( true ) { next = fgetc( fp ); if( next == '\r' ) continue; if( next == '\n' ) break; if( next == EOF ) break; line.add( next, 1 ); } // // check for valid line // if( !line.size() ) { if( next == EOF ) return false; else { name.add( "", 1 ); data.add( "", 1 ); return true; } } // // read the name value // while( line.get( &next, 1 ) ) { if( !name.size() ) if( ( next == ' ' ) || ( next == '!' ) ) continue; if( next == '=' ) break; name.add( next, 1 ); } // // verify the delimiter // if( next != '=' ) return true; // // read the data value // while( line.get( &next, 1 ) ) { if( !data.size() ) if( next == ' ' ) continue; data.add( next, 1 ); } // // trim the values // if( name.size() ) while( name.buff()[ name.size() - 1 ] == ' ' ) name.size( name.size() -1 ); if( data.size() ) while( data.buff()[ data.size() - 1 ] == ' ' ) data.size( data.size() -1 ); // // null terminate values // name.add( "", 1 ); data.add( "", 1 ); return true; } #ifndef OPT_DLLPROJ bool _CONFIG_MANAGER::file_pcf_load( CONFIG & config, const char * path, bool & need_certs ) { #ifdef WIN32 FILE * fp; if( fopen_s( &fp, path, "r" ) ) return false; #else FILE * fp = fopen( path, "r" ); if( fp == NULL ) return false; #endif // // set some sane defaults // config.set_number( "version", CONFIG_VERSION ); config.set_number( "network-ike-port", 500 ); config.set_number( "network-mtu-size", 1380 ); config.set_string( "client-auto-mode", "pull", 5 ); config.set_string( "client-iface", "virtual", 8 ); config.set_number( "client-addr-auto", 1 ); config.set_string( "network-natt-mode", "enable", 7 ); config.set_number( "network-natt-port", 4500 ); config.set_number( "network-natt-rate", 15 ); config.set_string( "network-frag-mode", "disable", 8 ); config.set_number( "network-frag-size", 540 ); config.set_number( "network-dpd-enable", 1 ); config.set_number( "network-notify-enable", 1 ); config.set_number( "client-banner-enable", 1 ); config.set_string( "auth-method", "mutual-psk-xauth", 17 ); config.set_string( "ident-server-type", "any", 4 ); config.set_string( "phase1-exchange", "aggressive", 11 ); config.set_string( "phase1-cipher", "auto", 5 ); config.set_string( "phase1-hash", "auto", 5 ); config.set_number( "phase1-dhgroup", 2 ); config.set_number( "phase1-life-secs", 86400 ); config.set_string( "phase2-transform", "auto", 5 ); config.set_string( "phase2-hmac", "auto", 5 ); config.set_number( "phase2-pfsgroup", 0 ); config.set_string( "ipcomp-transform", "disabled", 9 ); config.set_number( "client-dns-used", 1 ); config.set_number( "client-dns-auto", 1 ); config.set_number( "client-dns-suffix-auto", 1 ); config.set_number( "client-splitdns-used", 1 ); config.set_number( "client-splitdns-auto", 1 ); config.set_number( "client-wins-used", 1 ); config.set_number( "client-wins-auto", 1 ); config.set_number( "phase2-life-secs", 3600 ); config.set_number( "phase2-life-kbytes", 0 ); config.set_number( "policy-nailed", 0 ); config.set_number( "policy-list-auto", 1 ); // // parse the file contents // long auth_type = 1; bool idtype_set = false; BDATA name; BDATA data; while( read_line_pcf( fp, name, data ) ) { // // Skip invalid name or value lengths // if( ( name.size() <= 1 ) || ( data.size() <= 1 ) ) continue; // // Convert the appropriate values // if( !_stricmp( name.text(), "Host" ) && data.size() ) config.set_string( "network-host", data.text(), data.size() ); if( !_stricmp( name.text(), "AuthType" ) && data.size() ) { auth_type = atol( data.text() ); switch( auth_type ) { case 1: config.set_string( "auth-method", "mutual-psk-xauth", 17 ); need_certs = false; break; case 3: config.set_string( "auth-method", "mutual-rsa-xauth", 17 ); need_certs = true; break; case 5: config.set_string( "auth-method", "hybrid-grp-xauth", 17 ); need_certs = true; break; default: goto parse_fail; } } if( !_stricmp( name.text(), "GroupName" ) && data.size() ) { idtype_set = true; config.set_string( "ident-client-type", "keyid", 6 ); config.set_string( "ident-client-data", data.text(), data.size() ); } if( !_stricmp( name.text(), "GroupPwd" ) && data.size() ) config.set_binary( "auth-mutual-psk", data ); if( !_stricmp( name.text(), "enc_GroupPwd" ) && data.size() ) { data.size( data.size() - 1 ); if( !data.hex_decode() ) goto parse_fail; // // decrypt cisco password // if( data.size() < 48 ) goto parse_fail; unsigned char key[ 40 ]; unsigned char one[ 20 ]; unsigned char two[ 20 ]; data.get( one, 20 ); data.get( two, 20 ); one[ 19 ] += 1; SHA_CTX ctx; SHA1_Init( &ctx ); SHA1_Update( &ctx, one, 20 ); SHA1_Final( key, &ctx ); one[ 19 ] += 2; SHA1_Init( &ctx ); SHA1_Update( &ctx, one, 20 ); SHA1_Final( key + 20, &ctx ); size_t pwlen = data.size() - 40; SHA1_Init( &ctx ); SHA1_Update( &ctx, data.buff() + 40, pwlen ); SHA1_Final( one, &ctx ); if( memcmp( one, two, 20 ) ) goto parse_fail; BDATA pwd; data.get( pwd ); EVP_CIPHER_CTX ctx_cipher; EVP_CIPHER_CTX_init( &ctx_cipher ); EVP_CipherInit_ex( &ctx_cipher, EVP_des_ede3_cbc(), NULL, key, data.buff(), 0 ); EVP_Cipher( &ctx_cipher, pwd.buff(), pwd.buff(), ( unsigned int ) pwd.size() ); pwlen -= pwd.buff()[ pwd.size() - 1 ]; pwd.size( pwlen ); config.set_binary( "auth-mutual-psk", pwd ); } if( !_stricmp( name.text(), "DHGroup" ) && data.size() ) { long dh_group = atol( data.text() ); config.set_number( "phase1-dhgroup", dh_group ); } if( !_stricmp( name.text(), "EnableNat" ) && data.size() ) { long enable_nat = atol( data.text() ); if( enable_nat ) config.set_string( "network-natt-mode", "enable", 7 ); else config.set_string( "network-natt-mode", "disable", 8 ); } if( !_stricmp( name.text(), "Username" ) && data.size() ) config.set_string( "client-saved-username", data.text(), data.size() ); } // // add local identity type for pcf // files without a GroupName line // if( !idtype_set ) { switch( auth_type ) { case 1: // mutual-psk-xauth config.set_string( "ident-client-type", "address", 6 ); break; case 3: // mutual-rsa-xauth case 5: // hybrid-grp-xauth config.set_string( "ident-client-type", "asn1dn", 6 ); break; default: goto parse_fail; } } fclose( fp ); return true; parse_fail: fclose( fp ); return false; } #endif ike-2.2.1+dfsg/source/libip/000077500000000000000000000000001223036517100156025ustar00rootroot00000000000000ike-2.2.1+dfsg/source/libip/CMakeLists.txt000066400000000000000000000016671223036517100203540ustar00rootroot00000000000000# # Shrew Soft VPN / IP Utility Library # Cross Platform Make File # # author : Matthew Grooms # : mgrooms@shrew.net # : Copyright 2007, Shrew Soft Inc # include_directories( ${IKE_SOURCE_DIR}/source ${IKE_SOURCE_DIR}/source/libidb ${IKE_SOURCE_DIR}/source/liblog ${IKE_SOURCE_DIR}/source/libith ) add_library( ss_ip SHARED libip.frag.cpp libip.packet.cpp libip.packet.dns.cpp libip.packet.ip.cpp libip.packet.udp.cpp libip.pcap.cpp libip.queue.cpp libip.route.cpp ) target_link_libraries( ss_ip ss_idb ) set_target_properties( ss_ip PROPERTIES VERSION ${RELVER} SOVERSION ${RELVER} ) if( APPLE ) set( MACOSX_BUNDLE_BUNDLE_NAME "ShrewSoftIp" ) set_property( TARGET ss_ip PROPERTY FRAMEWORK ON ) set_property( TARGET ss_ip PROPERTY OUTPUT_NAME ${MACOSX_BUNDLE_BUNDLE_NAME} ) endif( APPLE ) install( TARGETS ss_ip LIBRARY DESTINATION ${PATH_LIB} FRAMEWORK DESTINATION "/Library/Frameworks" ) ike-2.2.1+dfsg/source/libip/libip.frag.cpp000066400000000000000000000246601223036517100203330ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "libip.h" #include _IPFRAG::_IPFRAG() { lastchk = 0; } // // is this packet a fragment // bool _IPFRAG::isfrag( PACKET_IP & packet ) { // // obtain the packet ip header // IP_HEADER * ip_header = ( IP_HEADER * ) packet.buff(); // // is this packet a fragment // unsigned short flags = htons( ip_header->flags ); if( ( flags & IP_FLAG_MORE ) || ( flags & IP_MASK_OFFSET ) ) return true; return false; } // // check for the do not fragment flag // bool _IPFRAG::dnfrag( PACKET_IP & packet ) { // // obtain the packet ip header // IP_HEADER * ip_header = ( IP_HEADER * ) packet.buff(); // // is this packet a fragment // unsigned short flags = htons( ip_header->flags ); if( flags & IP_FLAG_DONT_FRAG ) return true; return false; } bool _IPFRAG::dofrag( PACKET_IP & packet, PACKET_IP & fragment, size_t & offset, size_t max_size ) { // // determine packet ip header size // IP_HEADER * ip_header = ( IP_HEADER * ) packet.buff(); unsigned short ip_hdsize = 4 * ( ip_header->verlen & 0xF ); // // determine total payload size // size_t pld_size; pld_size = packet.size(); pld_size -= ip_hdsize; // // determine fragment payload size // size_t frg_size; frg_size = pld_size; frg_size -= offset; if( frg_size > ( max_size - sizeof( IP_HEADER ) ) ) frg_size = ( max_size - sizeof( IP_HEADER ) ); // // calculate payload left // size_t pld_left = 0; pld_left = pld_size; pld_left -= ( offset + frg_size ); // // will this be the last fragment // bool more = false; if( pld_left != 0 ) { more = true; // // there are more packet fragments to // follow, the ip standard states that // the three least significant bits are // discarded in the fragment offset // frg_size &= ( ~7 ); } // // calculate fragment buffer start // unsigned char * frg_buff; frg_buff = packet.buff(); frg_buff += ip_hdsize; frg_buff += offset; // // create the new packet fragment // in_addr addr_src; in_addr addr_dst; addr_src.s_addr = ip_header->ip_src; addr_dst.s_addr = ip_header->ip_dst; fragment.write( addr_src, addr_dst, ip_header->ident, ip_header->protocol ); fragment.add( frg_buff, frg_size ); fragment.frag( more, offset ); fragment.done(); // // determine next packet offset // offset += frg_size; return more; } bool _IPFRAG::defrag_add( PACKET_IP & fragment, unsigned short & id ) { // // cleanup any stale fragments // but only once per second // time_t current = time( NULL ); if( lastchk < current ) { lastchk = current; // // step through all our fragments // long count = used.count(); long index = 0; for( ; index < count; index++ ) { // // get the next fragment in our list // IPFRAG_ENTRY * entry = static_cast( used.get_entry( index ) ); assert( entry != NULL ); // // ckeck this fragment to see if // it has expired // if( entry->expire <= current ) { // // remove the fragment from the used // list and move it to the free list // used.del_entry( entry ); free.add_entry( entry ); // // correct for our change in list // index and item count // index--; count--; } } } // // attempt to aquire a frag entry from // our free list. if none are available // then create one if appropriate // IPFRAG_ENTRY * entry = NULL; if( free.count() > 0 ) entry = static_cast( free.del_entry( 0 ) ); else { long count = used.count() + free.count(); if( count < IPFRAG_MAX_FRAGCOUNT ) entry = new IPFRAG_ENTRY(); } if( entry == NULL ) return false; // // store the ip packet data in our entry // entry->expire = current + IPFRAG_MAX_LIFETIME; entry->packet.set( fragment ); // // obtain the packet ip header and record // the ip identity // IP_HEADER * ip_header = ( IP_HEADER * ) fragment.buff(); id = ip_header->ident; // // add this fragment to our used list // return used.add_entry( entry ); } bool _IPFRAG::defrag_chk( unsigned short ident ) { // // check to see if we have a complete list // of ip fragments for a given ip identity // unsigned long next_offset = 0; unsigned long temp_offset = 0; while( true ) { // // find the next fragment based // on the fragmentation offset // long index = 0; long count = used.count(); for( ; index < count; index++ ) { // // get the next fragment in our list // IPFRAG_ENTRY * entry = static_cast( used.get_entry( index ) ); assert( entry != NULL ); // // ckeck the ip header identity to // see if it matches our identity // IP_HEADER * ip_header = ( IP_HEADER * ) entry->packet.buff(); unsigned short ip_hdsize = 4 * ( ip_header->verlen & 0xF ); if( ip_header->ident != ident ) continue; // // evaluate this fragments offset to // determine if its the next fragment // in our packet // unsigned short flags = ntohs( ip_header->flags ); temp_offset = ( flags & IP_MASK_OFFSET ) << 3; if( temp_offset != next_offset ) continue; // // calculate this fragments data size // to our running total and determine // if this was the last fragment in // our packet // next_offset += ntohs( ip_header->size ) - ip_hdsize; // // complete packet is available // if( !( flags & IP_FLAG_MORE ) ) return true; } // // next fragment not found // if( index >= count ) break; } // // complete packet is not available // return false; } bool _IPFRAG::defrag_get( unsigned short ident, PACKET_IP & packet ) { // // make sure we have a clean packet // packet.del(); // // assemble a complete packet from // a list of ip fragments given the // ip packet identity // unsigned long next_offset = 0; unsigned long temp_offset = 0; while( true ) { // // find the next fragment based // on the fragmentation offset // long count = used.count(); long index = 0; for( ; index < count; index++ ) { // // get the next fragment in our list // IPFRAG_ENTRY * entry = static_cast( used.get_entry( index ) ); assert( entry != NULL ); // // ckeck the ip header identity to // see if it matches our identity // IP_HEADER * ip_header = ( IP_HEADER * ) entry->packet.buff(); unsigned short ip_hdsize = 4 * ( ip_header->verlen & 0xF ); if( ip_header->ident != ident ) continue; // // evaluate this fragments offset to // determine if its the next fragment // in our packet // unsigned short flags = ntohs( ip_header->flags ); temp_offset = ( flags & IP_MASK_OFFSET ) << 3; if( temp_offset != next_offset ) continue; // // if this is the first fragment, // build a new ip header based on // first fragments ip header info // if( next_offset == 0 ) { in_addr addr_s; in_addr addr_d; addr_s.s_addr = ip_header->ip_src; addr_d.s_addr = ip_header->ip_dst; packet.write( addr_s, addr_d, ip_header->ident, ip_header->protocol ); } // // correct for our change in list // index and item count // index--; count--; // // calculate this fragments data size // and add it to our complete packet // unsigned short fragsize = ntohs( ip_header->size ) - ip_hdsize; packet.add( entry->packet.buff() + ip_hdsize, fragsize ); // // add this fragments data size to our // running offset // next_offset += fragsize; // // remove the fragment from our list // and free its resources // used.del_entry( entry ); free.add_entry( entry ); // // complete packet is available // if( !( flags & IP_FLAG_MORE ) ) { packet.done(); return true; } } // // we shouldn't ever get here but break // if we are missing a packet fragment // if( index >= count ) break; } // // return error // return false; } ike-2.2.1+dfsg/source/libip/libip.h000066400000000000000000000351631223036517100170620ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #ifndef _LIBIP_H_ #define _LIBIP_H_ #ifdef WIN32 # define MPR50 1 # include # include # include # include # include #endif #ifdef UNIX # ifdef __linux__ # include # include # include # include # include # include # include # include # include # include # else # include # include # include # include # include # include # include # endif #endif #include #include #include #include "export.h" #include "libidb.h" #define MEDIA_ETHERNET 0x0001 #define PROTO_IP 0x0800 #define PROTO_ARP 0x0806 #define IP_V4_VERLEN ( 4 << 4 ) | 5 #ifdef PROTO_IP_ICMP // microsoft punks! #undef PROTO_IP_ICMP #endif #define PROTO_IP_ICMP 0x01 #define PROTO_IP_IPIP 0x04 #define PROTO_IP_TCP 0x06 #define PROTO_IP_UDP 0x11 #define PROTO_IP_ESP 0x32 #define PROTO_IP_AH 0x33 #define PROTO_IP_IPCOMP 0x6C #define IP_PROTO_UDP_DHCPS 0x0043 #define IP_PROTO_UDP_DHCPC 0x0044 #define IP_FLAG_MORE 0x2000 #define IP_FLAG_DONT_FRAG 0x4000 #define IP_FLAG_RESERVED 0x8000 #define IP_MASK_OFFSET 0x1FFF #define UDP_PORT_DNS 0x0035 #define UDP_PORT_DHCPS 0x0043 #define UDP_PORT_DHCPC 0x0044 #define DNS_REQUEST 0x00 #define DNS_REPLY 0x01 #define DNS_OP_QUERY 0x00 #define DNS_OP_IQUERY 0x01 #define DNS_OP_STATUS 0x02 #define DNS_OP_NOTIFY 0x04 #define DNS_OP_UPDATE 0x05 #define DNS_AUTHORITY 0x01 #define DNS_RECURSION 0x01 #define DNS_CODE_OK 0x00 #define DNS_CODE_FORMAT 0x01 #define DNS_CODE_SERVER 0x02 #define DNS_CODE_DOMAIN 0x03 #define DNS_CODE_NOSUPPORT 0x04 #define DNS_CODE_REFUSED 0x05 #define DNS_CODE_XYDOMAIN 0x06 #define DNS_CODE_XYRRSET 0x07 #define DNS_CODE_NXRRSET 0x08 #define DNS_CODE_NOTAUTH 0x09 #define DNS_CODE_NOTZONE 0x0a #define DNS_CODE_BADVER 0x10 #define DNS_CODE_BADKEY 0x11 #define DNS_CODE_BADTIME 0x12 #define DNS_CODE_BADMODE 0x13 #define DNS_CODE_BADNAME 0x14 #define DNS_CODE_BADALG 0x15 #define DNS_TYPE_A 1 #define DNS_TYPE_NS 2 #define DNS_TYPE_CNAME 5 #define DNS_TYPE_SOA 6 #define DNS_TYPE_MB 7 #define DNS_TYPE_MG 8 #define DNS_TYPE_MR 9 #define DNS_TYPE_NULL 10 #define DNS_TYPE_WKS 11 #define DNS_TYPE_PTR 12 #define DNS_TYPE_HINFO 13 #define DNS_TYPE_MINFO 14 #define DNS_TYPE_MX 15 #define DNS_TYPE_TXT 16 #define DNS_TYPE_RP 17 #define DHCP_MAGIC 0x63538263 #define BOOTP_REQUEST 0x01 #define BOOTP_REPLY 0x02 #define BOOTP_HW_EHTERNET 0x01 #define BOOTP_HW_IPSEC 0x1f #define DHCP_MSG_DISCOVER 0x01 #define DHCP_MSG_OFFER 0x02 #define DHCP_MSG_REQUEST 0x03 #define DHCP_MSG_ACK 0x05 #define DHCP_OPT_ALIGN16 0x00 // 16bit option alignment #define DHCP_OPT_SUBMASK 0x01 // subnet mask #define DHCP_OPT_ROUTER 0x03 // router #define DHCP_OPT_DNSS 0x06 // dns server #define DHCP_OPT_DOMAIN 0x0f // domain name #define DHCP_OPT_HOSTNAME 0x0c // host name #define DHCP_OPT_MTU 0x1a // adapter mtu #define DHCP_OPT_RDSCVR 0x1f // router discover #define DHCP_OPT_ROUTES 0x21 // static routes #define DHCP_OPT_VENDOR 0x2b // vendor specific #define DHCP_OPT_NBNS 0x2c // netbios name server #define DHCP_OPT_NBNT 0x2e // netbios node type #define DHCP_OPT_NBOTS 0x2f // netbios over tcp scope #define DHCP_OPT_ADDRESS 0x32 // requested address #define DHCP_OPT_LEASE 0x33 // lease period #define DHCP_OPT_MSGTYPE 0x35 // message type #define DHCP_OPT_SERVER 0x36 // server address #define DHCP_OPT_PARAMS 0x37 // parameters #define DHCP_OPT_CLASSID 0x3c // vendor identity #define DHCP_OPT_CLIENTID 0x3d // client identity #define DHCP_OPT_AUTOCONF 0xfb // auto configure #define DHCP_OPT_END 0xff // no more options #define ARP_REQUEST 0x0001 #define ARP_RESPONSE 0x0002 #define TCPDUMP_MAGIC 0xa1b2c3d4 #define RAWNET_BUFF_SIZE 8192 #define IPFRAG_MAX_LIFETIME 8 #define IPFRAG_MAX_FRAGCOUNT 64 #pragma pack( 1 ) typedef struct _ETH_HEADER { uint8_t mac_dst[ 6 ]; uint8_t mac_src[ 6 ]; uint16_t prot; }ETH_HEADER; typedef struct _ARP_HEADER { uint16_t media; uint16_t proto; uint8_t addr_len_media; uint8_t addr_len_proto; uint16_t opcode; }ARP_HEADER; typedef struct ARP_PAYLOAD_V4 { uint8_t src_addr_media[ 6 ]; uint32_t src_addr_proto; uint8_t dst_addr_media[ 6 ]; uint32_t dst_addr_proto; }ARP_PAYLOAD_V4; typedef struct _IP_HEADER { uint8_t verlen; // <4 bits : ip version // >4 bits : header length in 32bit words uint8_t tos; // 8 bits : type of service ( DSCP ) uint16_t size; // 16 bits : size of ip datagram uint16_t ident; // 16 bits : identity uint16_t flags; // 16 bits : flags & fragmentation offset uint8_t ttl; // 8 bits : time to live uint8_t protocol; // 8 bits : ip protocol uint16_t checksum; // 16 bits : header checksum uint32_t ip_src; // 32 bits : source ip address uint32_t ip_dst; // 32 bits : destination ip address // uint32_t options; // 32 bits : ip options }IP_HEADER; typedef struct _UDP_HEADER { uint16_t port_src; // 16 bits : source port uint16_t port_dst; // 16 bits : destination port uint16_t size; // 16 bits : size of udp datagram uint16_t checksum; // 16 bits : udp checksum }UDP_HEADER; typedef struct _ESP_HEADER { uint32_t spi; // 32 bits : security parameter index uint32_t seq; // 32 bits : sequence number }ESP_HEADER; typedef struct _AH_HEADER { uint8_t next; // 8 bits : next payload uint8_t len; // 8 bits : payload length uint16_t resrved; // 16 bits : payload length uint32_t spi; // 32 bits : security parameter index uint32_t seq; // 32 bits : sequence number }AH_HEADER; typedef struct _IPCOMP_HEADER { uint8_t next; // 8 bits : next payload uint8_t flags; // 8 bits : option flags uint16_t cpi; // 16 bits : compression parameter index }IPCOMP_HEADER; typedef struct _DNS_HEADER { uint16_t ident; // 16 bits : identification uint16_t flags; // 16 bits : dns option flags uint16_t ques; // 16 bits : total questions uint16_t answ; // 16 bits : total answer RRs uint16_t ath_rr; // 16 bits : total authority RRs uint16_t add_rr; // 16 bits : total additional RRs }DNS_HEADER; typedef struct _DHCP_HEADER { uint8_t op; // 8 bits : operation uint8_t htype; // 8 bits : hw address type uint8_t hlen; // 8 bits : hw address length uint8_t hops; // 8 bits : router hop count uint32_t xid; // 32 bits : transaction id uint16_t secs; // 16 bits : seconds elapsed uint16_t flags; // 16 bits : flags uint32_t ciaddr; // 32 bits : client ip address uint32_t yiaddr; // 32 bits : 'your' ip address uint32_t siaddr; // 32 bits : server ip address uint32_t giaddr; // 32 bits : relay agent ip address uint8_t chaddr[ 16 ]; // 16 bytes : client hw address uint8_t sname[ 64 ]; // 64 bytes : optional server host name uint8_t file[ 128 ]; // 128 bytes : boot file name uint32_t magic; // 32 bits : magic cookie // options }DHCP_HEADER; #pragma pack() // // adapted from winpcap pcap.h // #define PCAP_VERSION_MAJOR 2 #define PCAP_VERSION_MINOR 4 struct pcap_file_header { uint32_t magic; u_short version_major; u_short version_minor; int32_t thiszone; // gmt to local correction uint32_t sigfigs; // accuracy of timestamps uint32_t snaplen; // max length saved portion of each pkt uint32_t linktype; // data link type (LINKTYPE_*) }; struct pcap_pkthdr { uint32_t ts_sec; // time stamp seconds uint32_t ts_usec; // time stamp microseconds uint32_t caplen; // length of portion present uint32_t len; // length this packet (off wire) }; // // packet classes // typedef class DLX _PACKET : public _BDATA, public IDB_ENTRY { public: bool add_byte( uint8_t data ); bool add_word( uint16_t data, bool hton = true ); bool add_quad( uint32_t data, bool hton = true ); bool add_null( size_t size ); bool get_byte( uint8_t & data ); bool get_word( uint16_t & data, bool ntoh = true ); bool get_quad( uint32_t & data, bool ntoh = true ); bool get_null( size_t size ); }PACKET; typedef class DLX _PACKET_IP : public _PACKET { protected: uint16_t checksum(); public: bool write( in_addr addr_src, in_addr addr_dst, unsigned short ident, unsigned char prot ); bool read( in_addr & addr_src, in_addr & addr_dst, unsigned char & prot ); bool frag( bool more = false, size_t oset = 0 ); bool done(); }PACKET_IP; typedef class DLX _PACKET_UDP : public _PACKET { protected: uint16_t checksum( in_addr addr_src, in_addr addr_dst ); public: bool write( unsigned short port_src, unsigned short port_dst ); bool read( unsigned short & port_src, unsigned short & port_dst ); bool done( in_addr addr_src, in_addr addr_dst ); }PACKET_UDP; typedef struct DLX _DNS_QUERY : public IDB_ENTRY { char * name; unsigned short type; unsigned short clss; }DNS_QUERY; typedef struct DLX _DNS_RECORD : public IDB_ENTRY { char * name; unsigned short type; unsigned short clss; unsigned long rttl; unsigned short rlen; }DNS_RECORD; typedef class DLX _PACKET_DNS : public _PACKET { private: IDB_LIST list_ques; IDB_LIST list_answ; IDB_LIST list_ath_rr; IDB_LIST list_add_rr; bool read_name( char * name, long & size ); bool read_query( DNS_QUERY ** query ); bool read_record( DNS_RECORD ** record ); public: uint16_t ident; uint16_t flags; uint16_t ques; uint16_t answ; uint16_t ath_rr; uint16_t add_rr; _PACKET_DNS(); ~_PACKET_DNS(); bool write(); bool read(); bool get_question( DNS_QUERY ** query, long index ); bool get_answer( DNS_RECORD ** record, long index ); bool get_authority( DNS_RECORD ** record, long index ); bool get_additional( DNS_RECORD ** record, long index ); }PACKET_DNS; typedef class _IPFRAG_ENTRY : IDB_ENTRY { friend class _IPFRAG; time_t expire; PACKET_IP packet; }IPFRAG_ENTRY; typedef class DLX _IPFRAG { private: IDB_LIST used; IDB_LIST free; time_t lastchk; public: _IPFRAG(); bool isfrag( PACKET_IP & packet ); bool dnfrag( PACKET_IP & packet ); bool dofrag( PACKET_IP & packet, PACKET_IP & fragment, size_t & offset, size_t max_size ); bool defrag_add( PACKET_IP & packet, unsigned short & id ); bool defrag_chk( unsigned short id ); bool defrag_get( unsigned short id, PACKET_IP & packet ); }IPFRAG; typedef class DLX _IPQUEUE : private IDB_LIST { public: _IPQUEUE(); virtual ~_IPQUEUE(); bool add( PACKET_IP & packet ); bool get( PACKET_IP & packet, long index ); long count(); void clean(); }IPQUEUE; typedef class DLX _IPROUTE_ENTRY : public IDB_ENTRY { public: _IPROUTE_ENTRY & operator =( _IPROUTE_ENTRY & source ); _IPROUTE_ENTRY(); bool local; in_addr iface; in_addr addr; in_addr mask; in_addr next; }IPROUTE_ENTRY; #ifndef WIN32 typedef class DLX _IPROUTE_LIST : private IDB_LIST { public: _IPROUTE_LIST(); virtual ~_IPROUTE_LIST(); bool add( IPROUTE_ENTRY & route ); bool get( IPROUTE_ENTRY & route ); long count(); void clean(); }IPROUTE_LIST; #endif typedef class DLX _IPROUTE { private: int seq; unsigned long osver_maj; unsigned long osver_min; #ifndef WIN32 IPROUTE_LIST route_list; #endif public: #ifdef WIN32 bool iface_metric( unsigned long & metric, unsigned long index ); bool iface_2_addr( in_addr & iface, in_addr & gateway, unsigned long index ); bool addr_2_iface( unsigned long & index, in_addr iface ); #endif public: _IPROUTE(); bool add( IPROUTE_ENTRY & route ); bool del( IPROUTE_ENTRY & route ); bool get( IPROUTE_ENTRY & route ); bool best( IPROUTE_ENTRY & route ); bool increment( in_addr addr, in_addr mask ); bool decrement( in_addr addr, in_addr mask ); bool islocal( in_addr & iface ); bool flusharp( in_addr & iface ); }IPROUTE; typedef class DLX _PCAP_DUMP { private: FILE * fp; public: _PCAP_DUMP(); ~_PCAP_DUMP(); bool open( char * path ); void close(); bool dump( unsigned char * buff, size_t size ); bool dump( ETH_HEADER & header, PACKET_IP & packet ); bool flush(); }PCAP_DUMP; #endif ike-2.2.1+dfsg/source/libip/libip.packet.cpp000066400000000000000000000061051223036517100206550ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "libip.h" bool _PACKET::add_byte( uint8_t data ) { return add( &data, sizeof( data ) ); } bool _PACKET::add_word( uint16_t data, bool hton ) { if( hton ) data = htons( data ); return add( &data, sizeof( data ) ); } bool _PACKET::add_quad( uint32_t data, bool hton ) { if( hton ) data = htonl( data ); return add( &data, sizeof( data ) ); } bool _PACKET::add_null( size_t size ) { return add( 0, size ); } bool _PACKET::get_byte( uint8_t & data ) { return get( &data, sizeof( data ) ); } bool _PACKET::get_word( uint16_t & data, bool ntoh ) { if( !get( &data, sizeof( data ) ) ) return false; if( ntoh ) data = ntohs( data ); return true; } bool _PACKET::get_quad( uint32_t & data, bool ntoh ) { if( !get( &data, sizeof( data ) ) ) return false; if( ntoh ) data = ntohl( data ); return true; } bool _PACKET::get_null( size_t size ) { return get( ( void * ) NULL, size ); } ike-2.2.1+dfsg/source/libip/libip.packet.dns.cpp000066400000000000000000000165461223036517100214520ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "libip.h" #include #define MAX_DNS_NAME 255 PACKET_DNS::_PACKET_DNS() { ident = 0; flags = 0; ques = 0; answ = 0; ath_rr = 0; add_rr = 0; } PACKET_DNS::~_PACKET_DNS() { list_ques.clean(); list_answ.clean(); list_ath_rr.clean(); list_add_rr.clean(); } bool PACKET_DNS::read_name( char * name, long & size ) { uint8_t tag1; uint8_t tag2; long oset = 0; // // reserve room for our null char // size--; // // step through all sequence tags // while( get_byte( tag1 ) ) { // // is this a reserved value // if( ( ( tag1 & 0xc0 ) == 0x80 ) || ( ( tag1 & 0xc0 ) == 0x40 ) ) break; // // is this an end tag // if( tag1 == 0 ) { // // end of our segment, null // terminate and return // name[ oset ] = 0; return true; } // // append a period if neccessary // if( oset ) { if( size < 1 ) break; name[ oset ] = '.'; oset++; size--; } // // is this a name segment or // name segment pointer // if( ( tag1 & 0xc0 ) == 0xc0 ) { size_t tmp_oset = 0; size_t new_oset = 0; // // its a pointer, recurse // if( !get_byte( tag2 ) ) break; new_oset |= ( tag1 & 0x3f ); new_oset <<= 8; new_oset |= tag2; if( new_oset >= data_size ) break; tmp_oset = data_oset; data_oset = new_oset; bool rslt = read_name( name + oset, size ); data_oset = tmp_oset; if( rslt ) return true; } else { // // its a segment, append // long temp = tag1; if( temp >= size ) break; if( !get( &name[ oset ], temp ) ) break; oset += temp; size -= temp; } } return false; } bool PACKET_DNS::read_query( DNS_QUERY ** query ) { // // read the name // char name_data[ MAX_DNS_NAME ]; long name_size = MAX_DNS_NAME; if( !read_name( name_data, name_size ) ) return false; uint16_t type; if( !get_word( type ) ) return false; uint16_t clss; if( !get_word( clss ) ) return false; // // create our query struct // DNS_QUERY * tmp_query = new DNS_QUERY; if( tmp_query == NULL ) return false; tmp_query->name = new char[ name_size + 1 ]; memcpy( tmp_query->name, name_data, name_size ); tmp_query->name[ name_size ] = 0; tmp_query->type = type; tmp_query->clss = clss; *query = tmp_query; return true; } bool PACKET_DNS::read_record( DNS_RECORD ** record ) { // // read the name // char name_data[ MAX_DNS_NAME ]; long name_size = MAX_DNS_NAME; if( !read_name( name_data, name_size ) ) return false; uint16_t type; if( !get_word( type ) ) return false; uint16_t clss; if( !get_word( clss ) ) return false; uint32_t rttl; if( !get_quad( rttl ) ) return false; uint16_t rlen; if( !get_word( rlen ) ) return false; get_null( rlen ); // // create our record struct // DNS_RECORD * tmp_record = new DNS_RECORD; if( tmp_record == NULL ) return false; tmp_record->name = new char[ name_size + 1 ]; memcpy( tmp_record->name, name_data, name_size ); tmp_record->name[ name_size ] = 0; tmp_record->type = type; tmp_record->clss = clss; tmp_record->rttl = rttl; tmp_record->rlen = rlen; *record = tmp_record; return true; } bool PACKET_DNS::read() { // // read the header // DNS_HEADER dns_head; if( !get( &dns_head, sizeof( dns_head ) ) ) return false; ident = ntohs( dns_head.ident ); flags = ntohs( dns_head.flags ); ques = ntohs( dns_head.ques ); answ = ntohs( dns_head.answ ); ath_rr = ntohs( dns_head.ath_rr ); add_rr = ntohs( dns_head.add_rr ); // // read question section // long index; for( index = 0; index < ques; index++ ) { DNS_QUERY * query; if( !read_query( &query ) ) return false; list_ques.add_entry( query ); } // // read answer section // for( index = 0; index < answ; index++ ) { DNS_RECORD * record; if( !read_record( &record ) ) return false; list_answ.add_entry( record ); } // // authoritative section // for( index = 0; index < ath_rr; index++ ) { DNS_RECORD * record; if( !read_record( &record ) ) return false; list_ath_rr.add_entry( record ); } // // additional section // for( index = 0; index < add_rr; index++ ) { DNS_RECORD * record; if( !read_record( &record ) ) return false; list_add_rr.add_entry( record ); } return true; } bool PACKET_DNS::write() { return true; } bool PACKET_DNS::get_question( DNS_QUERY ** query, long index ) { *query = static_cast( list_ques.get_entry( index ) ); return ( *query != NULL ); } bool PACKET_DNS::get_answer( DNS_RECORD ** record, long index ) { *record = static_cast(list_answ.get_entry( index ) ); return ( *record != NULL ); } bool PACKET_DNS::get_authority( DNS_RECORD ** record, long index ) { *record = static_cast( list_ath_rr.get_entry( index ) ); return ( *record != NULL ); } bool PACKET_DNS::get_additional( DNS_RECORD ** record, long index ) { *record = static_cast( list_add_rr.get_entry( index ) ); return ( *record != NULL ); } ike-2.2.1+dfsg/source/libip/libip.packet.ip.cpp000066400000000000000000000077551223036517100213000ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "libip.h" uint16_t _PACKET_IP::checksum() { uint16_t * data = ( uint16_t * ) data_buff; uint16_t size = sizeof( IP_HEADER ); uint32_t cksum = 0; while( size > 1 ) { cksum += *data++; size -= sizeof( uint16_t ); } if( size ) cksum += *( uint8_t * ) data; while( cksum >> 16 ) cksum = ( cksum & 0xffff ) + ( cksum >> 16 ); return ( ( uint16_t ) ~cksum ); } bool _PACKET_IP::read( in_addr & addr_src, in_addr & addr_dst, unsigned char & prot ) { IP_HEADER ip_header; data_oset = 0; if( !get( &ip_header, sizeof( IP_HEADER ) ) ) return false; unsigned short ip_hdsize = 4 * ( ip_header.verlen & 0xF ); addr_src.s_addr = ip_header.ip_src; addr_dst.s_addr = ip_header.ip_dst; prot = ip_header.protocol; if( ip_hdsize > data_oset ) get_null( ip_hdsize - data_oset ); return true; } bool _PACKET_IP::write( in_addr addr_src, in_addr addr_dst, unsigned short ident, unsigned char prot ) { del(); IP_HEADER ip_header; ip_header.verlen = IP_V4_VERLEN; ip_header.tos = 0; ip_header.size = 0; ip_header.ident = ident; ip_header.flags = 0; ip_header.ttl = 64; ip_header.protocol = prot; ip_header.ip_src = addr_src.s_addr; ip_header.ip_dst = addr_dst.s_addr; ip_header.checksum = 0; return add( &ip_header, sizeof( ip_header ) ); } bool _PACKET_IP::frag( bool more, size_t oset ) { // // set packet fragmentation flags // IP_HEADER * ip_header = ( IP_HEADER * ) data_buff; if( more ) ip_header->flags |= htons( IP_FLAG_MORE ); if( oset ) ip_header->flags |= htons( short( oset >> 3 ) ); return true; } bool _PACKET_IP::done() { // // set ident, size and checksum // IP_HEADER * ip_header = ( IP_HEADER * ) data_buff; ip_header->size = htons( ( unsigned short ) data_size ); ip_header->checksum = 0; ip_header->checksum = checksum(); return true; } ike-2.2.1+dfsg/source/libip/libip.packet.udp.cpp000066400000000000000000000077151223036517100214540ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "libip.h" uint16_t _PACKET_UDP::checksum( in_addr addr_src, in_addr addr_dst ) { unsigned char * data = data_buff; size_t size = data_size; size_t oset = 0; uint32_t cksum = 0; for( ; ( oset + 1 ) < size; oset += 2 ) { cksum += ( ( data[ oset ] << 8 ) & 0xff00 ); cksum += ( data[ oset + 1 ] & 0x00ff ); } if( oset < size ) cksum += ( ( data[ oset ] << 8 ) & 0xff00 ); cksum += htons( ( uint16_t ) ( addr_src.s_addr >> 16 ) & 0xffff ); cksum += htons( ( uint16_t ) addr_src.s_addr & 0xffff ); cksum += htons( ( uint16_t ) ( addr_dst.s_addr >> 16 ) & 0xffff ); cksum += htons( ( uint16_t ) addr_dst.s_addr & 0xffff ); cksum += PROTO_IP_UDP; cksum += size; while( cksum >> 16 ) cksum = ( cksum & 0xffff ) + ( cksum >> 16 ); return htons( ( uint16_t ) ~cksum ); } bool _PACKET_UDP::read( unsigned short & port_src, unsigned short & port_dst ) { data_oset = 0; if( data_size < ( long ) sizeof( UDP_HEADER ) ) return false; UDP_HEADER udp_header; get( &udp_header, sizeof( udp_header ) ); port_src = udp_header.port_src; port_dst = udp_header.port_dst; return true; } bool _PACKET_UDP::write( unsigned short port_src, unsigned short port_dst ) { del(); UDP_HEADER udp_header; udp_header.port_src = port_src; udp_header.port_dst = port_dst; udp_header.size = 0; udp_header.checksum = 0; return ins( &udp_header, sizeof( udp_header ) ); } bool _PACKET_UDP::done( in_addr addr_src, in_addr addr_dst ) { // // sanity checks // if( data_size < ( long ) sizeof( UDP_HEADER ) ) return false; // // write size and calc checksum // UDP_HEADER * udp_header = ( UDP_HEADER * ) data_buff; udp_header->size = htons( ( unsigned short ) data_size ); udp_header->checksum = 0; udp_header->checksum = checksum( addr_src, addr_dst ); return true; } ike-2.2.1+dfsg/source/libip/libip.pcap.cpp000066400000000000000000000074161223036517100203370ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "libip.h" _PCAP_DUMP::_PCAP_DUMP() { fp = NULL; } _PCAP_DUMP::~_PCAP_DUMP() { close(); } bool _PCAP_DUMP::open( char * path ) { if( path == NULL ) return false; close(); // // create file // #ifdef WIN32 if( fopen_s( &fp, path, "w+b" ) ) return false; #else fp = fopen( path, "w+b" ); if( fp == NULL ) return false; #endif // // write pcap file header // pcap_file_header pfh; pfh.magic = TCPDUMP_MAGIC; pfh.version_major = PCAP_VERSION_MAJOR; pfh.version_minor = PCAP_VERSION_MINOR; pfh.thiszone = 0; pfh.sigfigs = 0; pfh.snaplen = 1514; pfh.linktype = 1; fwrite( &pfh, sizeof( pfh ), 1, fp ); return true; } void _PCAP_DUMP::close() { if( fp != NULL ) { // fflush( fp ); // fclose( fp ); fp = NULL; } } bool _PCAP_DUMP::dump( unsigned char * buff, size_t size ) { if( fp == NULL ) return false; pcap_pkthdr pph; pph.ts_sec = 0; pph.ts_usec = 0; pph.caplen = ( uint32_t ) size; pph.len = ( uint32_t ) size; fwrite( &pph, sizeof( pph ), 1, fp ); fwrite( buff, size, 1, fp ); return true; } bool _PCAP_DUMP::dump( ETH_HEADER & header, PACKET_IP & packet ) { if( fp == NULL ) return false; pcap_pkthdr pph; pph.ts_sec = 0; pph.ts_usec = 0; pph.caplen = ( uint32_t ) packet.size() + sizeof( ETH_HEADER ); pph.len = ( uint32_t ) packet.size() + sizeof( ETH_HEADER ); fwrite( &pph, sizeof( pph ), 1, fp ); fwrite( &header, sizeof( header ), 1, fp ); fwrite( packet.buff(), packet.size(), 1, fp ); return true; } bool _PCAP_DUMP::flush() { if( fp == NULL ) return false; fflush( fp ); return true; } ike-2.2.1+dfsg/source/libip/libip.queue.cpp000066400000000000000000000054071223036517100205360ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "libip.h" _IPQUEUE::_IPQUEUE() { } _IPQUEUE::~_IPQUEUE() { clean(); } bool _IPQUEUE::add( PACKET_IP & packet ) { PACKET_IP * qpacket = new PACKET_IP; if( qpacket == NULL ) return false; qpacket->add( packet ); if( !add_entry( qpacket ) ) { delete qpacket; return false; } return true; } bool _IPQUEUE::get( PACKET_IP & packet, long index ) { PACKET_IP * qpacket = static_cast( get_entry( index ) ); if( qpacket == NULL ) return false; packet = *qpacket; return true; } long _IPQUEUE::count() { return IDB_LIST::count(); } void _IPQUEUE::clean() { IDB_LIST::clean(); } ike-2.2.1+dfsg/source/libip/libip.route.cpp000066400000000000000000000577351223036517100205630ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "libip.h" void text_route( IPROUTE_ENTRY & route, char * text, bool dstonly = false ) { char txt_iface[ 24 ]; char txt_addr[ 24 ]; char txt_mask[ 24 ]; char txt_next[ 24 ]; if( dstonly ) { strcpy( txt_addr, inet_ntoa( route.addr )); strcpy( txt_mask, inet_ntoa( route.mask )); sprintf( text, "%s/%s", txt_addr, txt_mask ); } else { strcpy( txt_iface, inet_ntoa( route.iface )); strcpy( txt_addr, inet_ntoa( route.addr )); strcpy( txt_mask, inet_ntoa( route.mask )); strcpy( txt_next, inet_ntoa( route.next )); sprintf( text, "%s/%s gw %s if %s", txt_addr, txt_mask, txt_next, txt_iface ); } } //============================================================================== // Route entry class //============================================================================== _IPROUTE_ENTRY::_IPROUTE_ENTRY() { local = false; memset( &iface, 0, sizeof( in_addr ) ); memset( &addr, 0, sizeof( in_addr ) ); memset( &mask, 0, sizeof( in_addr ) ); memset( &next, 0, sizeof( in_addr ) ); } _IPROUTE_ENTRY & _IPROUTE_ENTRY::operator =( _IPROUTE_ENTRY & entry ) { local = entry.local; memcpy( &iface, &entry.iface, sizeof( in_addr ) ); memcpy( &addr, &entry.addr, sizeof( in_addr ) ); memcpy( &mask, &entry.mask, sizeof( in_addr ) ); memcpy( &next, &entry.next, sizeof( in_addr ) ); return *this; } //============================================================================== // Route list class //============================================================================== _IPROUTE_LIST::_IPROUTE_LIST() { } _IPROUTE_LIST::~_IPROUTE_LIST() { clean(); } bool _IPROUTE_LIST::add( IPROUTE_ENTRY & route ) { IPROUTE_ENTRY * tmp_route = new IPROUTE_ENTRY; if( tmp_route == NULL ) return false; *tmp_route = route; add_entry( tmp_route ); return true; } bool _IPROUTE_LIST::get( IPROUTE_ENTRY & route ) { long index = 0; for( ; index < count(); index++ ) { IPROUTE_ENTRY * tmp_route = static_cast( get_entry( index ) ); assert( tmp_route != NULL ); if( tmp_route->addr.s_addr != route.addr.s_addr ) continue; if( tmp_route->mask.s_addr != route.mask.s_addr ) continue; route = *tmp_route; del_entry( tmp_route ); delete tmp_route; return true; } return false; } long _IPROUTE_LIST::count() { return IDB_LIST::count(); } void _IPROUTE_LIST::clean() { IDB_LIST::clean(); } //============================================================================== // BSD specific route handling //============================================================================== #ifndef __linux__ // // BSD macros used to simplify route address processing // #ifdef __APPLE__ #define RT_ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(uint32_t) - 1))) : sizeof(uint32_t)) #endif #ifndef RT_ROUNDUP #define RT_ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) #endif // // BSD route message wrapper struct // typedef struct _RTMSG { rt_msghdr hdr; char msg[ 2048 ]; }RTMSG; // // BSD route message send request function // int rtmsg_send( RTMSG * rtmsg ) { int s = socket( PF_ROUTE, SOCK_RAW, 0 ); if( s < 0 ) return -1; long l = rtmsg->hdr.rtm_msglen += sizeof( rtmsg->hdr ); if( write( s, rtmsg, l ) < 0 ) { close( s ); return -2; } return s; } // // BSD route message receive result function // bool rtmsg_recv( int s, int seq, IPROUTE_ENTRY * route ) { RTMSG rtmsg; memset( &rtmsg, 0, sizeof( rtmsg ) ); // read route result message pid_t pid = getpid(); long len; do { len = read( s, &rtmsg, sizeof( rtmsg ) ); if( len < 0 ) { close( s ); return false; } } while( ( rtmsg.hdr.rtm_seq != seq ) || ( rtmsg.hdr.rtm_pid != pid ) ); close( s ); if( ( rtmsg.hdr.rtm_errno ) || ( rtmsg.hdr.rtm_msglen > len ) || ( rtmsg.hdr.rtm_version != RTM_VERSION ) ) return false; route->local = true; if( rtmsg.hdr.rtm_flags & RTF_GATEWAY ) route->local = false; char * cp = rtmsg.msg; long ml = rtmsg.hdr.rtm_msglen; for( int i = 1; i; i <<= 1 ) { if( ml <= 0 ) break; if( !( rtmsg.hdr.rtm_addrs & i ) ) continue; // printf( "XXXXXXXXX ml = %lu XXXXXXXX\n", ml ); struct sockaddr * sa = ( struct sockaddr * ) cp; struct sockaddr_dl * dl = ( struct sockaddr_dl * ) sa; switch( i ) { case RTA_DST: // printf( "XXXXXXXXX RTA_DST->sa_len = %d/%lu XXXXXXXX\n", // sa->sa_len, RT_ROUNDUP( sa->sa_len ) ); if( sa->sa_family == AF_INET ) { route->addr = ( ( sockaddr_in * ) cp )->sin_addr; // printf( "XXXXXXXXX route->addr = %s XXXXXXXX\n", // inet_ntoa( route->addr ) ); } break; case RTA_GATEWAY: // printf( "XXXXXXXXX RTA_GATEWAY->sa_len = %d/%lu XXXXXXXX\n", // sa->sa_len, RT_ROUNDUP( sa->sa_len ) ); if( sa->sa_family == AF_INET ) { route->next = ( ( sockaddr_in * ) cp )->sin_addr; // printf( "XXXXXXXXX route->next = %s XXXXXXXX\n", // inet_ntoa( route->next ) ); } break; case RTA_NETMASK: // printf( "XXXXXXXXX RTA_NETMASK->sa_len = %d/%lu XXXXXXXX\n", // sa->sa_len, RT_ROUNDUP( sa->sa_len ) ); if( sa->sa_family == AF_INET ) { route->mask = ( ( sockaddr_in * ) cp )->sin_addr; // printf( "XXXXXXXXX route->mask = %s XXXXXXXX\n", // inet_ntoa( route->mask ) ); } break; case RTA_GENMASK: // printf( "XXXXXXXXX RTA_GENMASK->sa_len = %d/%lu XXXXXXXX\n", // sa->sa_len, RT_ROUNDUP( sa->sa_len ) ); break; case RTA_IFP: // printf( "XXXXXXXXX RTA_IFP->sa_len = %d/%lu RTA_IFP->sdl_nlen = %d ( %s ) XXXXXXXX\n", // sa->sa_len, RT_ROUNDUP( sa->sa_len ), dl->sdl_nlen, dl->sdl_data ); break; case RTA_IFA: // printf( "XXXXXXXXX RTA_IFA->sa_len = %d/%lu XXXXXXXX\n", // sa->sa_len, RT_ROUNDUP( sa->sa_len ) ); if( sa->sa_family == AF_INET ) { route->iface = ( ( sockaddr_in * ) cp )->sin_addr; // printf( "XXXXXXXXX route->iface = %s XXXXXXXX\n", // inet_ntoa( route->iface ) ); } break; default: // printf( "XXXXXXXXX 0x%04x->sa_len = %d/%lu XXXXXXXX\n", i, // sa->sa_len, RT_ROUNDUP( sa->sa_len ) ); break; } cp += RT_ROUNDUP( sa->sa_len ); ml -= RT_ROUNDUP( sa->sa_len ); } return true; } // // BSD IPROUTE class // _IPROUTE::_IPROUTE() { seq = 0; } // add a route bool _IPROUTE::add( IPROUTE_ENTRY & route ) { // set route message header RTMSG rtmsg; memset( &rtmsg, 0, sizeof( rtmsg ) ); rtmsg.hdr.rtm_version = RTM_VERSION; rtmsg.hdr.rtm_seq = ++seq; rtmsg.hdr.rtm_type = RTM_ADD; rtmsg.hdr.rtm_flags = RTF_UP | RTF_STATIC | RTF_GATEWAY; rtmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY; rtmsg.hdr.rtm_addrs |= RTA_NETMASK; // add route destination sockaddr_in * dst = ( sockaddr_in * ) rtmsg.msg; dst->sin_family = AF_INET; dst->sin_len = sizeof( sockaddr_in ); dst->sin_addr = route.addr; rtmsg.hdr.rtm_msglen += sizeof( sockaddr_in ); // add route gateway sockaddr_in * gwy = ( sockaddr_in * )( rtmsg.msg + rtmsg.hdr.rtm_msglen ); gwy->sin_family = AF_INET; gwy->sin_len = sizeof( sockaddr_in ); gwy->sin_addr = route.next; rtmsg.hdr.rtm_msglen += sizeof( sockaddr_in ); // add route netmask sockaddr_in * msk = ( sockaddr_in * )( rtmsg.msg + rtmsg.hdr.rtm_msglen ); msk->sin_family = AF_INET; msk->sin_len = sizeof( sockaddr_in ); msk->sin_addr = route.mask; rtmsg.hdr.rtm_msglen += sizeof( sockaddr_in ); // send route add message int s = rtmsg_send( &rtmsg ); if( s < 0 ) return false; close( s ); return true; } // delete a route bool _IPROUTE::del( IPROUTE_ENTRY & route ) { // set route message header RTMSG rtmsg; memset( &rtmsg, 0, sizeof( rtmsg ) ); rtmsg.hdr.rtm_version = RTM_VERSION; rtmsg.hdr.rtm_seq = ++seq; rtmsg.hdr.rtm_type = RTM_DELETE; rtmsg.hdr.rtm_flags = RTF_UP | RTF_STATIC | RTF_GATEWAY; rtmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY; rtmsg.hdr.rtm_addrs |= RTA_NETMASK; // add route destination sockaddr_in * dst = ( sockaddr_in * ) rtmsg.msg; dst->sin_family = AF_INET; dst->sin_len = sizeof( sockaddr_in ); dst->sin_addr = route.addr; rtmsg.hdr.rtm_msglen += sizeof( sockaddr_in ); // add route gateway sockaddr_in * gwy = ( sockaddr_in * )( rtmsg.msg + rtmsg.hdr.rtm_msglen ); gwy->sin_family = AF_INET; gwy->sin_len = sizeof( sockaddr_in ); gwy->sin_addr = route.next; rtmsg.hdr.rtm_msglen += sizeof( sockaddr_in ); // add route netmask sockaddr_in * msk = ( sockaddr_in * )( rtmsg.msg + rtmsg.hdr.rtm_msglen ); msk->sin_family = AF_INET; msk->sin_len = sizeof( sockaddr_in ); msk->sin_addr = route.mask; rtmsg.hdr.rtm_msglen += sizeof( sockaddr_in ); // send route delete message int s = rtmsg_send( &rtmsg ); if( s < 0 ) return false; close( s ); return true; } // get a route ( by addr and mask ) bool _IPROUTE::get( IPROUTE_ENTRY & route ) { // set route message header RTMSG rtmsg; memset( &rtmsg, 0, sizeof( rtmsg ) ); rtmsg.hdr.rtm_version = RTM_VERSION; rtmsg.hdr.rtm_type = RTM_GET; rtmsg.hdr.rtm_seq = ++seq; rtmsg.hdr.rtm_flags = RTF_UP | RTF_STATIC | RTF_STATIC; rtmsg.hdr.rtm_addrs = RTA_DST; // add route destination sockaddr_in * dst = ( sockaddr_in * ) rtmsg.msg; dst->sin_family = AF_INET; dst->sin_len = sizeof( sockaddr_in ); dst->sin_addr = route.addr; rtmsg.hdr.rtm_msglen += sizeof( sockaddr_in ); // add route netmask sockaddr_in * msk = ( sockaddr_in * )( rtmsg.msg + rtmsg.hdr.rtm_msglen ); msk->sin_family = AF_INET; msk->sin_len = sizeof( sockaddr_in ); msk->sin_addr = route.mask; rtmsg.hdr.rtm_msglen += sizeof( sockaddr_in ); // send route get message int s = rtmsg_send( &rtmsg ); if( s < 0 ) return false; // read route result message return rtmsg_recv( s, seq, &route ); } // get best route ( by address ) bool _IPROUTE::best( IPROUTE_ENTRY & route ) { // set route message header RTMSG rtmsg; memset( &rtmsg, 0, sizeof( rtmsg ) ); rtmsg.hdr.rtm_version = RTM_VERSION; rtmsg.hdr.rtm_type = RTM_GET; rtmsg.hdr.rtm_seq = ++seq; rtmsg.hdr.rtm_flags = RTF_UP | RTF_HOST | RTF_STATIC; rtmsg.hdr.rtm_addrs = RTA_DST | RTA_IFP; // add route destination sockaddr_in * dst = ( sockaddr_in * ) rtmsg.msg; dst->sin_family = AF_INET; dst->sin_len = sizeof( sockaddr_in ); dst->sin_addr = route.addr; rtmsg.hdr.rtm_msglen += sizeof( sockaddr_in ); // add route interface sockaddr_dl * ifp = ( sockaddr_dl * )( rtmsg.msg + rtmsg.hdr.rtm_msglen ); ifp->sdl_family = AF_LINK; ifp->sdl_len = sizeof( sockaddr_dl ); rtmsg.hdr.rtm_msglen += sizeof( sockaddr_dl ); // send route get message int s = rtmsg_send( &rtmsg ); if( s < 0 ) return false; // read route result message return rtmsg_recv( s, seq, &route ); } // // BSD unix systems don't support multiple routes // to the same destination network. We go for the // lowest common denominator. Cache the existing // route information and delete the existing route // on increment. Retrieve and restore the previous // route on decrement. // // increment route costs bool _IPROUTE::increment( in_addr addr, in_addr mask ) { // // locate the most specific route for the destination // IPROUTE_ENTRY route; route.addr = addr; route.mask = mask; if( !get( route ) ) return true; // // does this route match the destination exactly // if( route.addr.s_addr != addr.s_addr ) return true; if( route.mask.s_addr != mask.s_addr ) return true; if( route.local ) return true; // // add a route entry to our route list // route_list.add( route ); // // delete the existing route // return del( route ); } // decrement route costs bool _IPROUTE::decrement( in_addr addr, in_addr mask ) { // // locate the cached route info for the destination // IPROUTE_ENTRY route; route.addr = addr; route.mask = mask; if( !route_list.get( route ) ) return true; // // delete the restore the route for the destination // return add( route ); } #else //============================================================================== // Linux specific route handling //============================================================================== // // netlink message wrapper struct // typedef struct _NLMSG { struct nlmsghdr hdr; struct rtmsg msg; char buff[ 1024 ]; }NLMSG; // // Linux IPROUTE class // _IPROUTE::_IPROUTE() { seq = 0; } // // Linux generic route message functions // unsigned int mask_to_prefix( in_addr mask ) { unsigned int plen = 0; unsigned int hmsk = ntohl( mask.s_addr ); plen = 0; while( hmsk & 0x80000000 ) { hmsk <<= 1; plen++; } return plen; } unsigned int prefix_to_mask( int plen ) { unsigned int mask = 0; for( int i = 0; i < plen; i++ ) { mask >>= 1; mask |= 0x80000000; } return htonl( mask ); } int rtmsg_send( NLMSG * nlmsg ) { int s = socket( PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE ); if( s < 0 ) return -1; static struct sockaddr_nl sanl; memset( &sanl, 0, sizeof( sanl ) ); sanl.nl_family = AF_NETLINK; sanl.nl_pid = getpid(); if( bind( s, ( struct sockaddr * ) &sanl, sizeof( sanl ) ) < 0 ) { close( s ); return -2; } if( send( s, nlmsg, nlmsg->hdr.nlmsg_len, 0 ) < 0 ) { close( s ); return -3; } return s; } bool rtmsg_recv( int s, IPROUTE_ENTRY & route ) { char buff[ sizeof( NLMSG ) ]; memset( &buff, 0, sizeof( NLMSG ) ); int rslt = recv( s, buff, sizeof( NLMSG ), 0 ); close( s ); if( rslt <= 0 ) return false; struct nlmsghdr * nlmsg = ( struct nlmsghdr * ) buff; int nllen = rslt; while( NLMSG_OK( nlmsg, nllen ) ) { // printf( "XX : netlink msg type = %i\n", nlmsg->nlmsg_type ); if( nlmsg->nlmsg_type == RTM_NEWROUTE ) { // printf( "XX : netlink msg type = NLMSG_NEWROUTE\n" ); struct rtmsg * rtmsg = ( struct rtmsg * ) NLMSG_DATA( nlmsg ); int rtlen = RTM_PAYLOAD( nlmsg ); struct rtattr * rta = ( struct rtattr * ) RTM_RTA( rtmsg ); while( RTA_OK( rta, rtlen ) ) { switch( rta->rta_type ) { case RTA_DST: // printf( "XX : netlink attribute = RTA_DST\n" ); memcpy( &route.addr, RTA_DATA( rta ), sizeof( route.addr ) ); route.mask.s_addr = prefix_to_mask( rtmsg->rtm_dst_len ); break; case RTA_GATEWAY: // printf( "XX : netlink attribute = RTA_GATEWAY\n" ); memcpy( &route.next, RTA_DATA( rta ), sizeof( route.next ) ); break; case RTA_OIF: { // printf( "XX : netlink attribute = RTA_OIF\n" ); struct ifreq ifr; int r = socket( PF_PACKET, SOCK_RAW, 0 ); if( r > 0 ) { ifr.ifr_ifindex = *( ( int * ) RTA_DATA( rta ) ); ioctl( r, SIOCGIFNAME, &ifr ); ifr.ifr_addr.sa_family = AF_INET; ioctl( r, SIOCGIFADDR, &ifr ); route.iface = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; close( r ); } break; } case RTA_PREFSRC: // printf( "XX : netlink attribute = RTA_PREFSRC\n" ); break; case RTA_METRICS: // printf( "XX : netlink attribute = RTA_METRICS\n" ); break; case RTA_CACHEINFO: // printf( "XX : netlink attribute = RTA_CACHEINFO\n" ); break; default: // printf( "XX : unhandled route attribute %i\n", rta->rta_type ); break; } rta = RTA_NEXT( rta, rtlen ); } return true; } if( nlmsg->nlmsg_type == RTM_DELROUTE ) { // printf( "XX : netlink msg type = NLMSG_DELROUTE\n" ); } if( nlmsg->nlmsg_type == RTM_GETROUTE ) { // printf( "XX : netlink msg type = NLMSG_GETROUTE\n" ); } if( nlmsg->nlmsg_type == NLMSG_ERROR ) { // printf( "XX : netlink msg type = NLMSG_ERROR\n" ); break; } if( nlmsg->nlmsg_type == NLMSG_DONE ) { // printf( "XX : netlink msg type = NLMSG_DONE\n" ); break; } nlmsg = NLMSG_NEXT( nlmsg, nllen ); } return false; } // add a route bool _IPROUTE::add( IPROUTE_ENTRY & route ) { // set route message header NLMSG nlmsg; memset( &nlmsg, 0, sizeof( nlmsg ) ); nlmsg.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE; nlmsg.hdr.nlmsg_type = RTM_NEWROUTE; nlmsg.msg.rtm_family = AF_INET; nlmsg.msg.rtm_table = RT_TABLE_MAIN; nlmsg.msg.rtm_protocol = RTPROT_STATIC; nlmsg.msg.rtm_scope = RT_SCOPE_UNIVERSE; nlmsg.msg.rtm_type = RTN_UNICAST; // add route destination struct rtattr * rta = ( struct rtattr * ) nlmsg.buff; rta->rta_type = RTA_DST; rta->rta_len = sizeof( struct rtattr ); struct in_addr * dst = ( in_addr * )( ( ( char * ) rta ) + sizeof( struct rtattr ) ); *dst = route.addr; rta->rta_len += sizeof( route.addr ); nlmsg.hdr.nlmsg_len += rta->rta_len; // add route gateway rta = ( struct rtattr * )( nlmsg.buff + nlmsg.hdr.nlmsg_len ); rta->rta_type = RTA_GATEWAY; rta->rta_len = sizeof( struct rtattr ); struct in_addr * gwy = ( in_addr * )( ( ( char * ) rta ) + sizeof( struct rtattr ) ); *gwy = route.next; rta->rta_len += sizeof( route.next ); nlmsg.hdr.nlmsg_len += rta->rta_len; // set route network mask nlmsg.msg.rtm_dst_len = mask_to_prefix( route.mask ); // set final message length nlmsg.hdr.nlmsg_len += sizeof( struct rtmsg ); nlmsg.hdr.nlmsg_len = NLMSG_LENGTH( nlmsg.hdr.nlmsg_len ); int s = rtmsg_send( &nlmsg ); if( s < 0 ) return false; close( s ); return true; } // delete a route bool _IPROUTE::del( IPROUTE_ENTRY & route ) { // set route message header NLMSG nlmsg; memset( &nlmsg, 0, sizeof( nlmsg ) ); nlmsg.hdr.nlmsg_flags = NLM_F_REQUEST; nlmsg.hdr.nlmsg_type = RTM_DELROUTE; nlmsg.msg.rtm_family = AF_INET; nlmsg.msg.rtm_table = RT_TABLE_MAIN; nlmsg.msg.rtm_protocol = RTPROT_STATIC; nlmsg.msg.rtm_scope = RT_SCOPE_UNIVERSE; nlmsg.msg.rtm_type = RTN_UNICAST; // add route destination struct rtattr * rta = ( struct rtattr * ) nlmsg.buff; rta->rta_type = RTA_DST; rta->rta_len = sizeof( struct rtattr ); struct in_addr * dst = ( in_addr * )( ( ( char * ) rta ) + sizeof( struct rtattr ) ); *dst = route.addr; rta->rta_len += sizeof( route.addr ); nlmsg.hdr.nlmsg_len += rta->rta_len; // add route gateway rta = ( struct rtattr * )( nlmsg.buff + nlmsg.hdr.nlmsg_len ); rta->rta_type = RTA_GATEWAY; rta->rta_len = sizeof( struct rtattr ); struct in_addr * gwy = ( in_addr * )( ( ( char * ) rta ) + sizeof( struct rtattr ) ); *gwy = route.next; rta->rta_len += sizeof( route.next ); nlmsg.hdr.nlmsg_len += rta->rta_len; // set route network mask nlmsg.msg.rtm_dst_len = mask_to_prefix( route.mask ); // set final message length nlmsg.hdr.nlmsg_len += sizeof( struct rtmsg ); nlmsg.hdr.nlmsg_len = NLMSG_LENGTH( nlmsg.hdr.nlmsg_len ); int s = rtmsg_send( &nlmsg ); if( s < 0 ) return false; close( s ); return true; } // get a route ( by addr and mask ) bool _IPROUTE::get( IPROUTE_ENTRY & route ) { // set route message header NLMSG nlmsg; memset( &nlmsg, 0, sizeof( nlmsg ) ); nlmsg.hdr.nlmsg_flags = NLM_F_REQUEST; nlmsg.hdr.nlmsg_type = RTM_GETROUTE; nlmsg.msg.rtm_family = AF_INET; nlmsg.msg.rtm_table = RT_TABLE_MAIN; nlmsg.msg.rtm_protocol = RTPROT_STATIC; nlmsg.msg.rtm_scope = RT_SCOPE_UNIVERSE; nlmsg.msg.rtm_type = RTN_UNICAST; // add route destination struct rtattr * rta = ( struct rtattr * ) nlmsg.buff; rta->rta_type = RTA_DST; rta->rta_len = sizeof( struct rtattr ); struct in_addr * dst = ( in_addr * )( ( ( char * ) rta ) + sizeof( struct rtattr ) ); *dst = route.addr; rta->rta_len += sizeof( route.addr ); nlmsg.hdr.nlmsg_len += rta->rta_len; // set route network mask nlmsg.msg.rtm_dst_len = mask_to_prefix( route.mask ); // set final message length nlmsg.hdr.nlmsg_len += sizeof( struct rtmsg ); nlmsg.hdr.nlmsg_len = NLMSG_LENGTH( nlmsg.hdr.nlmsg_len ); int s = rtmsg_send( &nlmsg ); if( s < 0 ) return false; return rtmsg_recv( s, route ); } // get best route ( by address ) bool _IPROUTE::best( IPROUTE_ENTRY & route ) { // set route message header NLMSG nlmsg; memset( &nlmsg, 0, sizeof( nlmsg ) ); nlmsg.hdr.nlmsg_flags = NLM_F_REQUEST; nlmsg.hdr.nlmsg_type = RTM_GETROUTE; nlmsg.msg.rtm_family = AF_INET; nlmsg.msg.rtm_table = RT_TABLE_UNSPEC; nlmsg.msg.rtm_protocol = RTPROT_UNSPEC; nlmsg.msg.rtm_scope = RT_SCOPE_UNIVERSE; nlmsg.msg.rtm_type = RTN_UNSPEC; // add route destination struct rtattr * rta = ( struct rtattr * ) nlmsg.buff; rta->rta_type = RTA_DST; rta->rta_len = sizeof( struct rtattr ); struct in_addr * dst = ( in_addr * )( ( ( char * ) rta ) + sizeof( struct rtattr ) ); *dst = route.addr; rta->rta_len += sizeof( route.addr ); nlmsg.hdr.nlmsg_len += rta->rta_len; // set route network mask nlmsg.msg.rtm_dst_len = 32; // set final message length nlmsg.hdr.nlmsg_len += sizeof( struct rtmsg ); nlmsg.hdr.nlmsg_len = NLMSG_LENGTH( nlmsg.hdr.nlmsg_len ); int s = rtmsg_send( &nlmsg ); if( s < 0 ) return false; return rtmsg_recv( s, route ); } // // Linux systems appear to give priority to newer // routes so this is a no-op for now. // // decrement route costs bool _IPROUTE::increment( in_addr addr, in_addr mask ) { return true; } // decrement route costs bool _IPROUTE::decrement( in_addr addr, in_addr mask ) { return true; } #endif //============================================================================== // Shared unix route functions //============================================================================== // // flush arp table bool _IPROUTE::flusharp( in_addr & iface ) { return true; } ike-2.2.1+dfsg/source/libith/000077500000000000000000000000001223036517100157565ustar00rootroot00000000000000ike-2.2.1+dfsg/source/libith/CMakeLists.txt000066400000000000000000000014311223036517100205150ustar00rootroot00000000000000# # Shrew Soft VPN / Timer and Thread Library # Cross Platform Make File # # author : Matthew Grooms # : mgrooms@shrew.net # : Copyright 2007, Shrew Soft Inc # include_directories( ${IKE_SOURCE_DIR}/source ) add_library( ss_ith SHARED libith.cpp ) # Linux realtime library if( PATH_LIB_RT ) target_link_libraries( ss_ith rt ) endif( PATH_LIB_RT ) set_target_properties( ss_ith PROPERTIES VERSION ${RELVER} SOVERSION ${RELVER} ) if( APPLE ) set( MACOSX_BUNDLE_BUNDLE_NAME "ShrewSoftIth" ) set_property( TARGET ss_ith PROPERTY FRAMEWORK ON ) set_property( TARGET ss_ith PROPERTY OUTPUT_NAME ${MACOSX_BUNDLE_BUNDLE_NAME} ) endif( APPLE ) install( TARGETS ss_ith LIBRARY DESTINATION ${PATH_LIB} FRAMEWORK DESTINATION "/Library/Frameworks" ) ike-2.2.1+dfsg/source/libith/libith.cpp000066400000000000000000000671241223036517100177470ustar00rootroot00000000000000/* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "libith.h" //============================================================================== // mutex lock class //============================================================================== #ifdef WIN32 _ITH_LOCK::_ITH_LOCK() { memset( obj_name, 0, 20 ); hmutex = CreateMutex( NULL, false, NULL ); strcpy_s( obj_name, 20, "unknown" ); } _ITH_LOCK::~_ITH_LOCK() { CloseHandle( hmutex ); } void _ITH_LOCK::name( const char * set_name ) { strcpy_s( obj_name, 20, set_name ); } bool _ITH_LOCK::lock() { int result = WaitForSingleObject( hmutex, 3000 ); assert( result != WAIT_FAILED ); if( result != WAIT_FAILED ) return true; result = GetLastError(); printf( "XX : mutex lock failed, ERROR CODE %i\n", result ); return false; } bool _ITH_LOCK::unlock() { ReleaseMutex( hmutex ); return true; } #endif #ifdef UNIX _ITH_LOCK::_ITH_LOCK() { memset( obj_name, 0, 20 ); pthread_mutexattr_init( &attr ); pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_ERRORCHECK ); pthread_mutex_init( &mutex, &attr ); } _ITH_LOCK::~_ITH_LOCK() { pthread_mutex_destroy( &mutex ); pthread_mutexattr_destroy( &attr ); } void _ITH_LOCK::name( const char * set_name ) { strcpy_s( obj_name, 20, set_name ); } bool _ITH_LOCK::lock() { #ifdef OPT_TIMEDLOCK struct timespec ts; clock_gettime( CLOCK_REALTIME, &ts ); ts.tv_sec += 3; int result = pthread_mutex_timedlock( &mutex, &ts ); #else int result = pthread_mutex_lock( &mutex ); #endif switch( result ) { case 0: return true; case EINVAL: printf( "XX : mutex %s lock failed, invalid parameter\n", obj_name ); break; case ETIMEDOUT: printf( "XX : mutex %s lock failed, timeout expired\n", obj_name ); break; case EAGAIN: printf( "XX : mutex %s lock failed, recursion error\n", obj_name ); break; case EDEADLK: printf( "XX : mutex %s lock failed, mutex already owned\n", obj_name ); break; } assert( result == 0 ); return false; } bool _ITH_LOCK::unlock() { int result = pthread_mutex_unlock( &mutex ); switch( result ) { case 0: return true; case EINVAL: printf( "XX : mutex %s unlock failed, mutex not owned\n", obj_name ); break; } assert( result == 0 ); return false; } #endif //============================================================================== // alertable wait condition //============================================================================== #ifdef WIN32 _ITH_COND::_ITH_COND() { hevent = CreateEvent( NULL, TRUE, FALSE, NULL ); } _ITH_COND::~_ITH_COND() { CloseHandle( hevent ); } void _ITH_COND::name( const char * set_name ) { strcpy_s( obj_name, 20, set_name ); } bool _ITH_COND::wait( long msecs ) { if( msecs < 0 ) msecs = INFINITE; if( WaitForSingleObject( hevent, msecs ) == WAIT_OBJECT_0 ) return false; return true; } void _ITH_COND::alert() { SetEvent( hevent ); } void _ITH_COND::reset() { ResetEvent( hevent ); } #endif #ifdef UNIX _ITH_COND::_ITH_COND() { socketpair( AF_UNIX, SOCK_STREAM, 0, conn_wake ); fcntl( conn_wake[ 0 ], F_SETFL, O_NONBLOCK ); } _ITH_COND::~_ITH_COND() { if( conn_wake[ 0 ] != -1 ) { close( conn_wake[ 0 ] ); conn_wake[ 0 ] = -1; } if( conn_wake[ 1 ] != -1 ) { close( conn_wake[ 1 ] ); conn_wake[ 1 ] = -1; } } void _ITH_COND::name( const char * set_name ) { strcpy_s( obj_name, 20, set_name ); } bool _ITH_COND::wait( long msecs ) { // timeval expressed as seconds and microseconds timeval tval; timeval * ptval = NULL; if( msecs >= 0 ) { tval.tv_sec = msecs / 1000; tval.tv_usec = msecs % 1000 * 1000; ptval = &tval; } fd_set fds; FD_ZERO( &fds ); FD_SET( conn_wake[ 0 ], &fds ); select( conn_wake[ 0 ] + 1, &fds, NULL, NULL, ptval ); if( FD_ISSET( conn_wake[ 0 ], &fds ) ) return false; return true; } void _ITH_COND::alert() { char c = 0; long result = send( conn_wake[ 1 ], &c, 1, 0 ); } void _ITH_COND::reset() { char c = 0; long result = recv( conn_wake[ 0 ], &c, 1, 0 ); } #endif //============================================================================== // thread execution class //============================================================================== typedef struct _ITH_PARAM { ITH_EXEC * exec; void * arg; }ITH_PARAM; _ITH_EXEC::_ITH_EXEC() { } #ifdef WIN32 unsigned long __stdcall help( void * arg ) { ITH_PARAM * param = ( ITH_PARAM * ) arg; long result = param->exec->func( param->arg ); delete param; return result; } bool _ITH_EXEC::exec( void * arg ) { ITH_PARAM * param = new ITH_PARAM; if( param == NULL ) return false; param->exec = this; param->arg = arg; DWORD tid; CreateThread( NULL, 0, help, param, 0, &tid ); return true; } #endif #ifdef UNIX void * help( void * arg ) { ITH_PARAM * param = ( ITH_PARAM * ) arg; sigset_t signal_mask; sigemptyset( &signal_mask ); sigaddset( &signal_mask, SIGINT ); sigaddset( &signal_mask, SIGTERM ); pthread_sigmask( SIG_BLOCK, &signal_mask, NULL ); param->exec->func( param->arg ); delete param; return NULL; } bool _ITH_EXEC::exec( void * arg ) { ITH_PARAM * param = new ITH_PARAM; if( param == NULL ) return false; param->exec = this; param->arg = arg; pthread_create( &thread, NULL, &help, param ); pthread_detach( thread ); return true; } #endif //============================================================================== // event execution timer classes //============================================================================== _ITH_TIMER::_ITH_TIMER() { head = NULL; stop = false; exit = false; } _ITH_TIMER::~_ITH_TIMER() { while( head != NULL ) { ITH_ENTRY * next = head->next; delete head; head = next; } } #ifdef WIN32 void _ITH_TIMER::tval_cur( ITH_TIMEVAL & tval ) { SYSTEMTIME stime; memset( &stime, 0, sizeof( stime ) ); GetSystemTime( &stime ); FILETIME ftime; memset( &ftime, 0, sizeof( ftime ) ); SystemTimeToFileTime( &stime, &ftime ); memcpy( &tval, &ftime, sizeof( tval ) ); } void _ITH_TIMER::tval_add( ITH_TIMEVAL & tval, long lval ) { // ftime expressed as 100 nanosecond units ITH_TIMEVAL dval; dval.QuadPart = lval; dval.QuadPart *= 10000; tval.QuadPart += dval.QuadPart; } long _ITH_TIMER::tval_sub( ITH_TIMEVAL & tval1, ITH_TIMEVAL & tval2 ) { ITH_TIMEVAL dval; dval.QuadPart = tval2.QuadPart - tval1.QuadPart; return long( dval.QuadPart / 10000 ); } bool _ITH_TIMER::wait_time( long msecs ) { return cond.wait( msecs ); } #endif #ifdef UNIX void _ITH_TIMER::tval_cur( ITH_TIMEVAL & tval ) { gettimeofday( &tval, NULL ); } void _ITH_TIMER::tval_add( ITH_TIMEVAL & tval, long delay ) { // timeval expressed as seconds and microseconds tval.tv_sec += delay / 1000; tval.tv_usec += delay % 1000 * 1000; } long _ITH_TIMER::tval_sub( ITH_TIMEVAL & tval1, ITH_TIMEVAL & tval2 ) { long sec = tval2.tv_sec - tval1.tv_sec; sec *= 1000; long usec = tval2.tv_usec - tval1.tv_usec; usec /= 1000; return sec + usec; } bool _ITH_TIMER::wait_time( long msecs ) { return cond.wait( msecs ); } #endif void _ITH_TIMER::run() { lock.lock(); while( !stop ) { // // determine the time we must // wait before the next event // should be executed // long delay = -1; if( head != NULL ) { ITH_TIMEVAL current; tval_cur( current ); delay = tval_sub( current, head->sched ); if( delay < 0 ) delay = 0; } // // wait for calculated delay // lock.unlock(); bool result = wait_time( delay ); lock.lock(); // // if the wait returned false, // it returned before the time // period elapsed // if( !result ) { cond.reset(); continue; } // // check if we have an event // that needs to be enabled // if( head != NULL ) { ITH_TIMEVAL current; tval_cur( current ); // // make sure the head event // is ready to execute // if( tval_sub( current, head->sched ) > 0 ) continue; ITH_ENTRY * entry = head; head = head->next; // // execute the event // lock.unlock(); if( entry->event->func() ) add( entry->event ); delete entry; lock.lock(); } } exit = true; lock.unlock(); } void _ITH_TIMER::end() { stop = true; cond.alert(); } bool _ITH_TIMER::add( ITH_EVENT * event ) { ITH_ENTRY * entry = new ITH_ENTRY; if( entry == NULL ) return false; entry->event = event; tval_cur( entry->sched ); tval_add( entry->sched, event->delay ); lock.lock(); ITH_ENTRY * prev = NULL; ITH_ENTRY * next = head; while( next != NULL ) { if( tval_sub( next->sched, entry->sched ) <= 0 ) break; if( next == NULL ) break; prev = next; next = prev->next; } entry->next = next; if( prev == NULL ) head = entry; else prev->next = entry; cond.alert(); lock.unlock(); return true; } bool _ITH_TIMER::del( ITH_EVENT * event ) { ITH_ENTRY * prev = NULL; ITH_ENTRY * next = head; lock.lock(); while( next != NULL ) { if( next->event == event ) break; if( next == NULL ) break; prev = next; next = prev->next; } if( next != NULL ) { if( prev == NULL ) head = next->next; else prev->next = next->next; delete next; } lock.unlock(); return ( next != NULL ); } //============================================================================== // inter process communication classes //============================================================================== // // shared platform functions // long _ITH_IPCC::io_send( void *data, size_t size ) { char * buff = ( char * ) data; size_t sent = 0; size_t temp = 0; while( size > sent ) { temp = size - sent; long result = io_send( buff + sent, temp, temp ); switch( result ) { case IPCERR_OK: case IPCERR_BUFFER: break; default: return result; } sent += temp; } return IPCERR_OK; } long _ITH_IPCC::io_recv( void *data, size_t size ) { char * buff = ( char * ) data; size_t rcvd = 0; size_t temp = 0; while( size > rcvd ) { temp = size - rcvd; long result = io_recv( buff + rcvd, temp, temp ); switch( result ) { case IPCERR_OK: case IPCERR_BUFFER: break; default: return result; } rcvd += temp; } return IPCERR_OK; } #ifdef WIN32 // // inter process communication client // _ITH_IPCC::_ITH_IPCC() { hmutex_recv = CreateMutex( NULL, false, NULL ); hmutex_send = CreateMutex( NULL, false, NULL ); hevent_wake = CreateEvent( NULL, true, false, NULL ); conn = INVALID_HANDLE_VALUE; } _ITH_IPCC::~_ITH_IPCC() { detach(); if( hevent_wake != NULL ) { CloseHandle( hevent_wake ); hevent_wake = NULL; } if( hmutex_send != NULL ) { CloseHandle( hmutex_send ); hmutex_send = NULL; } if( hmutex_recv != NULL ) { CloseHandle( hmutex_recv ); hmutex_recv = NULL; } } void _ITH_IPCC::io_conf( IPCCONN sconn ) { conn = sconn; } VOID WINAPI io_send_complete( DWORD result, DWORD size, LPOVERLAPPED olapp ) { // nothing to do } long _ITH_IPCC::io_send( void * data, size_t size, size_t & sent ) { // if( conn == INVALID_HANDLE_VALUE ) // return IPCERR_CLOSED; DWORD dwsize = ( DWORD ) sent; WaitForSingleObject( hmutex_send, INFINITE ); // windows does not always set // the GetLastError value to // success after ReadFileEx but // the documentation says you // should check it for errors SetLastError( ERROR_SUCCESS ); memset( &olapp_send, 0, sizeof( olapp_send ) ); long result = WriteFileEx( conn, data, dwsize, &olapp_send, io_send_complete ); if( !result ) { result = WaitForSingleObject( hevent_wake, 0 ); // if( result == WAIT_OBJECT_0 ) // ResetEvent( hevent_wake ); ReleaseMutex( hmutex_send ); if( result == WAIT_OBJECT_0 ) return IPCERR_WAKEUP; return IPCERR_CLOSED; } result = GetLastError(); switch( result ) { case ERROR_SUCCESS: // // wait in an alertable state until // the operation completes or until // the wake event is signaled // result = WaitForSingleObjectEx( hevent_wake, INFINITE, true ); if( result == WAIT_OBJECT_0 ) { // ResetEvent( hevent_wake ); // cancel the current overlaped // request and give it a chance // to complete in a wait state CancelIo( conn ); ReleaseMutex( hmutex_recv ); return IPCERR_WAKEUP; } GetOverlappedResult( conn, &olapp_send, &dwsize, true ); result = GetLastError(); break; } switch( result ) { case ERROR_SUCCESS: result = IPCERR_OK; break; case ERROR_MORE_DATA: result = IPCERR_BUFFER; break; case ERROR_OPERATION_ABORTED: // ResetEvent( hevent_wake ); // result = IPCERR_WAKEUP; // break; case ERROR_BROKEN_PIPE: case ERROR_INVALID_HANDLE: result = IPCERR_CLOSED; break; default: result = IPCERR_NODATA; break; } sent = dwsize; ReleaseMutex( hmutex_send ); return result; } VOID WINAPI io_recv_complete( DWORD result, DWORD size, LPOVERLAPPED olapp ) { // nothing to do } long _ITH_IPCC::io_recv( void * data, size_t size, size_t & rcvd ) { // if( conn == INVALID_HANDLE_VALUE ) // return IPCERR_CLOSED; DWORD dwsize = ( DWORD ) size; WaitForSingleObject( hmutex_recv, INFINITE ); // windows does not always set // the GetLastError value to // success after ReadFileEx but // the documentation says you // should check it for errors SetLastError( ERROR_SUCCESS ); memset( &olapp_recv, 0, sizeof( olapp_recv ) ); long result = ReadFileEx( conn, data, dwsize, &olapp_recv, io_recv_complete ); if( !result ) { result = WaitForSingleObject( hevent_wake, 0 ); if( result == WAIT_OBJECT_0 ) ResetEvent( hevent_wake ); ReleaseMutex( hmutex_recv ); if( result == WAIT_OBJECT_0 ) return IPCERR_WAKEUP; return IPCERR_CLOSED; } result = GetLastError(); switch( result ) { case ERROR_SUCCESS: // // wait in an alertable state until // the operation completes or until // the wake event is signaled // result = WaitForSingleObjectEx( hevent_wake, INFINITE, true ); if( result == WAIT_OBJECT_0 ) { ResetEvent( hevent_wake ); // cancel the current overlaped // request and give it a chance // to complete in a wait state CancelIo( conn ); ReleaseMutex( hmutex_recv ); return IPCERR_WAKEUP; } GetOverlappedResult( conn, &olapp_recv, &dwsize, true ); result = GetLastError(); break; } switch( result ) { case ERROR_SUCCESS: result = IPCERR_OK; break; case ERROR_MORE_DATA: result = IPCERR_BUFFER; break; case ERROR_OPERATION_ABORTED: // ResetEvent( hevent_wake ); // result = IPCERR_WAKEUP; // break; case ERROR_BROKEN_PIPE: case ERROR_INVALID_HANDLE: result = IPCERR_CLOSED; break; default: result = IPCERR_NODATA; break; } rcvd = dwsize; ReleaseMutex( hmutex_recv ); return result; } long _ITH_IPCC::attach( const char * path, long timeout ) { if( !WaitNamedPipe( path, timeout ) ) return IPCERR_FAILED; conn = CreateFile( path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL ); if( conn == INVALID_HANDLE_VALUE ) { long result = GetLastError(); return IPCERR_FAILED; } return IPCERR_OK; } void _ITH_IPCC::wakeup() { if( hevent_wake != NULL ) SetEvent( hevent_wake ); } void _ITH_IPCC::detach() { if( conn != INVALID_HANDLE_VALUE ) { CancelIo( conn ); FlushFileBuffers( conn ); CloseHandle( conn ); conn = INVALID_HANDLE_VALUE; } } // // inter process communication server // _ITH_IPCS::_ITH_IPCS() { hevent_wake = CreateEvent( NULL, true, false, NULL ); hevent_conn = CreateEvent( NULL, true, false, NULL ); sid_server = NULL; sid_client = NULL; acl = NULL; psa = NULL; conn = INVALID_HANDLE_VALUE; } _ITH_IPCS::~_ITH_IPCS() { done(); if( hevent_conn != NULL ) { CloseHandle( hevent_conn ); hevent_conn = NULL; } if( hevent_wake != NULL ) { CloseHandle( hevent_wake ); hevent_wake = NULL; } } long _ITH_IPCS::init( const char * path, bool admin ) { // when creating a named pipe with explicit access, // you must specify FILE_CREATE_PIPE_INSTANCE for // an SID that is appropriate for the account that // owns your process. otherwise, after creating the // initial pipe instance and assigning the access // control, your process will loose its ability to // create more than one pipe instance ... really. long ea_count = 0; // admin sid SID_IDENTIFIER_AUTHORITY sia_nt = SECURITY_NT_AUTHORITY; if( !AllocateAndInitializeSid( &sia_nt, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &sid_server ) ) return IPCERR_FAILED; // initialize the explicit access info memset( &ea[ 0 ], sizeof( EXPLICIT_ACCESS ), 0 ); ea[ 0 ].grfAccessPermissions = GENERIC_READ | GENERIC_WRITE | FILE_CREATE_PIPE_INSTANCE; ea[ 0 ].grfAccessMode = SET_ACCESS; ea[ 0 ].grfInheritance= NO_INHERITANCE; ea[ 0 ].Trustee.TrusteeForm = TRUSTEE_IS_SID; ea[ 0 ].Trustee.TrusteeType = TRUSTEE_IS_GROUP; ea[ 0 ].Trustee.ptstrName = ( LPTSTR ) sid_server; ea_count++; if( !admin ) { // user sid if( !AllocateAndInitializeSid( &sia_nt, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &sid_client ) ) return IPCERR_FAILED; // initialize the explicit access info memset( &ea[ 1 ], sizeof( EXPLICIT_ACCESS ), 0 ); ea[ 1 ].grfAccessPermissions = GENERIC_READ | GENERIC_WRITE; ea[ 1 ].grfAccessMode = SET_ACCESS; ea[ 1 ].grfInheritance= NO_INHERITANCE; ea[ 1 ].Trustee.TrusteeForm = TRUSTEE_IS_SID; ea[ 1 ].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; ea[ 1 ].Trustee.ptstrName = ( LPTSTR ) sid_client; ea_count++; } // create a new ACL for the access if( SetEntriesInAcl( ea_count, ea, NULL, &acl ) != ERROR_SUCCESS ) return IPCERR_FAILED; // Initialize a security descriptor if( !InitializeSecurityDescriptor( &sd, SECURITY_DESCRIPTOR_REVISION ) ) return IPCERR_FAILED; // Add the ACL to the security descriptor. if( !SetSecurityDescriptorDacl( &sd, TRUE, acl, FALSE ) ) return IPCERR_FAILED; // Initialize a security attributes structure. sa.nLength = sizeof ( SECURITY_ATTRIBUTES ); sa.lpSecurityDescriptor = &sd; sa.bInheritHandle = FALSE; conn = CreateNamedPipe( path, FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 8192, 8192, 10, &sa ); if( conn == INVALID_HANDLE_VALUE ) return IPCERR_FAILED; return IPCERR_OK; } void _ITH_IPCS::done() { if( acl != NULL ) { LocalFree( acl ); acl = NULL; } if( sid_client != NULL ) { FreeSid( sid_client ); sid_client = NULL; } if( sid_server != NULL ) { FreeSid( sid_server ); sid_server = NULL; } if( conn != INVALID_HANDLE_VALUE ) { CloseHandle( conn ); conn = INVALID_HANDLE_VALUE; } } long _ITH_IPCS::inbound( const char * path, IPCCONN & ipcconn ) { DWORD dwundef; long result; if( conn == INVALID_HANDLE_VALUE ) { conn = CreateNamedPipe( path, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 8192, 8192, 10, &sa ); if( conn == INVALID_HANDLE_VALUE ) { result = GetLastError(); return IPCERR_FAILED; } } ipcconn = INVALID_HANDLE_VALUE; OVERLAPPED olapp; memset( &olapp, 0, sizeof( olapp ) ); olapp.hEvent = hevent_conn; SetLastError( ERROR_SUCCESS ); result = ConnectNamedPipe( conn, &olapp ); if( !result ) result = GetLastError(); switch( result ) { case ERROR_IO_PENDING: { HANDLE events[ 2 ] = { hevent_conn, hevent_wake }; result = WaitForMultipleObjects( 2, events, false, INFINITE ); if( result == WAIT_OBJECT_0 + 1 ) { // cancel the current overlaped // request and give it a chance // to complete in a wait state CancelIo( conn ); SleepEx( 0, true ); } result = GetOverlappedResult( conn, &olapp, &dwundef, false ); result = GetLastError(); break; } } switch( result ) { case ERROR_SUCCESS: case ERROR_PIPE_CONNECTED: ipcconn = conn; conn = INVALID_HANDLE_VALUE; result = IPCERR_OK; break; case ERROR_OPERATION_ABORTED: ResetEvent( hevent_wake ); result = IPCERR_WAKEUP; break; case ERROR_GEN_FAILURE: case ERROR_BROKEN_PIPE: case ERROR_INVALID_HANDLE: result = IPCERR_CLOSED; break; default: result = IPCERR_NODATA; break; } return result; } void _ITH_IPCS::wakeup() { SetEvent( hevent_wake ); } #endif #ifdef UNIX // // inter process communication client // _ITH_IPCC::_ITH_IPCC() { socketpair( AF_UNIX, SOCK_STREAM, 0, conn_wake ); conn = -1; } _ITH_IPCC::~_ITH_IPCC() { detach(); if( conn_wake[ 0 ] != -1 ) { close( conn_wake[ 0 ] ); conn_wake[ 0 ] = -1; } if( conn_wake[ 1 ] != -1 ) { close( conn_wake[ 1 ] ); conn_wake[ 1 ] = -1; } } void _ITH_IPCC::io_conf( IPCCONN sconn ) { conn = sconn; } long _ITH_IPCC::io_send( void * data, size_t size, size_t & sent ) { long result = send( conn, data, size, 0 ); if( result < 0 ) return IPCERR_FAILED; sent = result; return IPCERR_OK; } long _ITH_IPCC::io_recv( void * data, size_t size, size_t & rcvd ) { fd_set fds; FD_ZERO( &fds ); FD_SET( conn, &fds ); FD_SET( conn_wake[ 0 ], &fds ); int max = conn_wake[ 0 ]; if( max < conn ) max = conn; if( select( max + 1, &fds, NULL, NULL, NULL ) <= 0 ) return IPCERR_FAILED; if( FD_ISSET( conn, &fds ) ) { long result = recv( conn, data, size, 0 ); if( result < 0 ) return IPCERR_FAILED; if( result == 0 ) return IPCERR_CLOSED; rcvd = result; return IPCERR_OK; } if( FD_ISSET( conn_wake[ 0 ], &fds ) ) { char c; recv( conn_wake[ 0 ], &c, 1, 0 ); return IPCERR_WAKEUP; } return IPCERR_NODATA; } long _ITH_IPCC::attach( const char * path, long timeout ) { conn = socket( AF_UNIX, SOCK_STREAM, 0 ); if( conn == -1 ) return IPCERR_FAILED; if( socketpair( AF_UNIX, SOCK_STREAM, 0, conn_wake ) < 0 ) return IPCERR_FAILED; struct sockaddr_un saddr; saddr.sun_family = AF_UNIX; long sun_len = strlen( path ) + sizeof( saddr.sun_family ); #ifndef __linux__ sun_len += sizeof( saddr.sun_len ); saddr.sun_len = sun_len; #endif strcpy( saddr.sun_path, path ); if( connect( conn, ( struct sockaddr * ) &saddr, sun_len ) < 0 ) return IPCERR_FAILED; return IPCERR_OK; } void _ITH_IPCC::wakeup() { char c = 0; send( conn_wake[ 1 ], &c, 1, 0 ); } void _ITH_IPCC::detach() { if( conn != -1 ) close( conn ); } // // inter process communication server // _ITH_IPCS::_ITH_IPCS() { conn = -1; socketpair( AF_UNIX, SOCK_STREAM, 0, conn_wake ); } _ITH_IPCS::~_ITH_IPCS() { done(); if( conn_wake[ 0 ] != -1 ) { close( conn_wake[ 0 ] ); conn_wake[ 0 ] = -1; } if( conn_wake[ 1 ] != -1 ) { close( conn_wake[ 1 ] ); conn_wake[ 1 ] = -1; } } long _ITH_IPCS::init( const char * path, bool admin ) { unlink( path ); conn = socket( AF_UNIX, SOCK_STREAM, 0 ); if( conn == -1 ) return IPCERR_FAILED; struct sockaddr_un saddr; saddr.sun_family = AF_UNIX; long sun_len = strlen( path ) + sizeof( saddr.sun_family ); #ifndef __linux__ sun_len += sizeof( saddr.sun_len ); saddr.sun_len = sun_len; #endif strcpy( saddr.sun_path, path ); if( bind( conn, ( struct sockaddr * ) &saddr, sun_len ) < 0 ) return IPCERR_FAILED; if( !admin ) if( chmod( path, S_IRWXU | S_IRWXG | S_IRWXO ) < 0 ) return IPCERR_FAILED; if( listen( conn, 5 ) < 0 ) return IPCERR_FAILED; return IPCERR_OK; } void _ITH_IPCS::done() { if( conn != -1 ) close( conn ); } long _ITH_IPCS::inbound( const char * path, IPCCONN & ipcconn ) { fd_set fds; FD_ZERO( &fds ); FD_SET( conn, &fds ); FD_SET( conn_wake[ 0 ], &fds ); int max = conn_wake[ 0 ]; if( max < conn ) max = conn; if( select( max + 1, &fds, NULL, NULL, NULL ) <= 0 ) return IPCERR_FAILED; if( FD_ISSET( conn, &fds ) ) { ipcconn = accept( conn, NULL, NULL ); if( ipcconn < 0 ) return IPCERR_FAILED; return IPCERR_OK; } if( FD_ISSET( conn_wake[ 0 ], &fds ) ) { char c; recv( conn_wake[ 0 ], &c, 1, 0 ); return IPCERR_WAKEUP; } return IPCERR_NODATA; } void _ITH_IPCS::wakeup() { char c = 0; send( conn_wake[ 1 ], &c, 1, 0 ); } #endif ike-2.2.1+dfsg/source/libith/libith.h000066400000000000000000000153411223036517100174060ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #ifndef _LIBITH_H_ #define _LIBITH_H_ #ifdef WIN32 # include # include # include #endif #ifdef UNIX # ifdef __linux__ # include # include # include # include # include # include # include # include # include # include # include # else # include # include # include # include # include # include # include # include # include # include # include # endif # include "compat/winstring.h" #endif #include #include "export.h" // // Win32 specific // #ifdef WIN32 typedef LARGE_INTEGER ITH_TIMEVAL; #endif // // Unix specific // #ifdef UNIX typedef timeval ITH_TIMEVAL; #define Sleep( T ) usleep( T * 1000 ) #endif //============================================================================== // mutex lock class //============================================================================== typedef class DLX _ITH_LOCK { private: #ifdef WIN32 HANDLE hmutex; #endif #ifdef UNIX pthread_mutex_t mutex; pthread_mutexattr_t attr; #endif char obj_name[ 20 ]; public: _ITH_LOCK(); ~_ITH_LOCK(); void name( const char * set_name ); bool lock(); bool unlock(); }ITH_LOCK; //============================================================================== // alertable wait condition //============================================================================== typedef class DLX _ITH_COND { private: #ifdef WIN32 HANDLE hevent; #endif #ifdef UNIX int conn_wake[ 2 ]; #endif char obj_name[ 20 ]; public: _ITH_COND(); ~_ITH_COND(); void name( const char * set_name ); bool wait( long msecs ); void alert(); void reset(); }ITH_COND; //============================================================================== // thread execution class //============================================================================== typedef class DLX _ITH_EXEC { #ifdef UNIX pthread_t thread; #endif public: _ITH_EXEC(); bool exec( void * arg ); virtual long func( void * arg ) = 0; }ITH_EXEC; //============================================================================== // event execution timer classes //============================================================================== typedef class DLX _ITH_EVENT { public: long delay; virtual bool func() = 0; }ITH_EVENT; typedef struct _ITH_ENRTY { _ITH_ENRTY * next; _ITH_EVENT * event; ITH_TIMEVAL sched; }ITH_ENTRY; typedef class DLX _ITH_TIMER { private: ITH_ENTRY * head; ITH_LOCK lock; ITH_COND cond; bool stop; bool exit; void tval_cur( ITH_TIMEVAL & tval ); void tval_add( ITH_TIMEVAL & tval, long lval = 0 ); long tval_sub( ITH_TIMEVAL & tval1, ITH_TIMEVAL & tval2 ); bool wait_time( long msecs ); public: _ITH_TIMER(); virtual ~_ITH_TIMER(); void run(); void end(); bool add( ITH_EVENT * event ); bool del( ITH_EVENT * event ); }ITH_TIMER; //============================================================================== // inter process communication classes //============================================================================== #ifdef WIN32 #define IPCCONN HANDLE #endif #ifdef UNIX #define IPCCONN int #endif #define IPCTYPE_SYSIPC 1 #define IPCTYPE_SOCKET 2 #define IPCERR_OK 1 #define IPCERR_FAILED 2 #define IPCERR_BUFFER 3 #define IPCERR_WAKEUP 4 #define IPCERR_CLOSED 5 #define IPCERR_NODATA 6 typedef class DLX _ITH_IPCC { protected: #ifdef WIN32 HANDLE hmutex_send; HANDLE hmutex_recv; HANDLE hevent_wake; OVERLAPPED olapp_send; OVERLAPPED olapp_recv; #endif #ifdef UNIX int conn_wake[ 2 ]; #endif protected: IPCCONN conn; void io_conf( IPCCONN sconn ); long io_send( void * data, size_t size ); long io_send( void * data, size_t size, size_t & sent ); long io_recv( void * data, size_t size ); long io_recv( void * data, size_t size, size_t & rcvd ); public: _ITH_IPCC(); ~_ITH_IPCC(); long attach( const char * path, long timeout ); void wakeup(); void detach(); }ITH_IPCC; typedef class DLX _ITH_IPCS { private: #ifdef WIN32 HANDLE hevent_conn; HANDLE hevent_wake; PSID sid_server; PSID sid_client; PACL acl; EXPLICIT_ACCESS ea[ 2 ]; SECURITY_DESCRIPTOR sd; SECURITY_ATTRIBUTES sa; PSECURITY_ATTRIBUTES psa; #endif #ifdef UNIX int conn_wake[ 2 ]; #endif protected: IPCCONN conn; public: _ITH_IPCS(); ~_ITH_IPCS(); long init( const char * path, bool admin ); void done(); long inbound( const char * path, IPCCONN & ipcconn ); void wakeup(); }ITH_IPCS; #endif ike-2.2.1+dfsg/source/liblog/000077500000000000000000000000001223036517100157535ustar00rootroot00000000000000ike-2.2.1+dfsg/source/liblog/CMakeLists.txt000066400000000000000000000014031223036517100205110ustar00rootroot00000000000000# # Shrew Soft VPN / Log Facility Library # Cross Platform Make File # # author : Matthew Grooms # : mgrooms@shrew.net # : Copyright 2007, Shrew Soft Inc # include_directories( ${IKE_SOURCE_DIR}/source ${IKE_SOURCE_DIR}/source/libith ) add_library( ss_log SHARED liblog.cpp ) target_link_libraries( ss_log ss_ith ) set_target_properties( ss_log PROPERTIES VERSION ${RELVER} SOVERSION ${RELVER} ) if( APPLE ) set( MACOSX_BUNDLE_BUNDLE_NAME "ShrewSoftLog" ) set_property( TARGET ss_log PROPERTY FRAMEWORK ON ) set_property( TARGET ss_log PROPERTY OUTPUT_NAME ${MACOSX_BUNDLE_BUNDLE_NAME} ) endif( APPLE ) install( TARGETS ss_log LIBRARY DESTINATION ${PATH_LIB} FRAMEWORK DESTINATION "/Library/Frameworks" ) ike-2.2.1+dfsg/source/liblog/liblog.cpp000066400000000000000000000147471223036517100177440ustar00rootroot00000000000000/* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "liblog.h" _LOG::_LOG() { fp = NULL; } _LOG::~_LOG() { close(); } bool _LOG::write_buff( char * buff, size_t size ) { // // build time stamp // char tbuff[ LOG_MAX_TXT ]; size_t tlen = 0; if( !( log_flags & LOGFLAG_SYSTEM ) ) { time_t ctime; struct tm * ltime; time( &ctime ); #ifdef WIN32 struct tm ltm; ltime = <m; localtime_s( ltime, &ctime ); #endif #ifdef UNIX ltime = localtime( &ctime ); #endif tlen = strftime( tbuff, LOG_MAX_TXT, "%y/%m/%d %H:%M:%S ", ltime ); } lock.lock(); // // log buffer to console // if( log_flags & LOGFLAG_ECHO ) printf( "%s", buff ); // // log individual lines // char * line = buff; size_t oset = 0; size_t llen; while( line != NULL && line[ 0 ] ) { char * next = strchr( line, '\n' ); if( next != NULL ) { if( log_flags & LOGFLAG_SYSTEM ) next[ 0 ] = 0; next++; llen = next - line; } else llen = strlen( line ); if( tlen ) write_line( tbuff, tlen ); write_line( line, llen ); line = next; } lock.unlock(); return true; } bool _LOG::write_line( char * buff, size_t size ) { #ifdef WIN32 DWORD dwsize = ( DWORD ) size; if( fp != NULL ) WriteFile( fp, buff, dwsize, &dwsize, NULL ); #endif #ifdef UNIX if( log_flags & LOGFLAG_SYSTEM ) syslog( LOG_NOTICE, "%s", buff ); else { if( fp != NULL ) { fwrite( buff, size, 1, fp ); fflush( fp ); } } #endif return true; } bool _LOG::open( char * path, long level, long flags ) { // // set the log level // log_flags = flags; log_level = level; #ifdef WIN32 if( path ) { close(); fp = CreateFile( path, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0 ); if( fp == NULL ) return false; } #endif #ifdef UNIX if( path ) { if( log_flags & LOGFLAG_SYSTEM ) openlog( path, LOG_NDELAY, LOG_DAEMON ); else { fp = fopen( path, "w" ); if( fp == NULL ) return false; } } #endif return true; } void _LOG::close() { #ifdef WIN32 if( fp != NULL ) { FlushFileBuffers( fp ); CloseHandle( fp ); } #endif #ifdef UNIX if( log_flags & LOGFLAG_SYSTEM ) closelog(); else { if( fp != NULL ) { fflush( fp ); fclose( fp ); } } #endif fp = NULL; } void _LOG::txt( long level, const char * fmt, ... ) { char tbuff[ LOG_MAX_TXT ]; char fbuff[ LOG_MAX_TXT ]; if( level > log_level ) return; va_list list; va_start( list, fmt ); if( ( fp != NULL ) || ( log_flags & LOGFLAG_ECHO ) ) { size_t tsize = LOG_MAX_TXT; size_t tused = 0; vsprintf_s( tbuff, LOG_MAX_TXT, fmt, list ); sprintf_s( fbuff, tsize, "%s", tbuff ); write_buff( fbuff, tused ); } } void _LOG::bin( long level, long blevel, void * bin, size_t len, const char * fmt, ... ) { char tbuff[ LOG_MAX_TXT ]; char fbuff[ LOG_MAX_BIN ]; if( level > log_level ) return; va_list list; va_start( list, fmt ); if( ( fp != NULL ) || ( log_flags & LOGFLAG_ECHO ) ) { // tsize = total buffer size - NLx2 - NULL size_t tsize = LOG_MAX_BIN - 3; size_t tused = 0; // add our text label vsprintf_s( tbuff, LOG_MAX_TXT, fmt, list ); tused += sprintf_s( fbuff, tsize, "%s ( %ld bytes )", tbuff, len ); // check binary log level if( blevel <= log_level ) { // setup target and source data pointers char * tdata = fbuff; char * sdata = ( char * ) bin; // bsize = ( tsize / required chars per line ) * bin bytes per line size_t ssize = ( ( tsize - tused ) / 77 ) * 32; size_t sused = 0; if( ssize > len ) ssize = len; // format and log source bytes for( ; sused < ssize; sused++ ) { if( !( sused & 0x1F ) ) tused += sprintf_s( &tdata[ tused ], tsize - tused, "\n0x :" ); unsigned char bchar = sdata[ sused ]; if( !( sused & 0x03 ) ) tused += sprintf_s( &tdata[ tused ], tsize - tused, " %02x", bchar ); else tused += sprintf_s( &tdata[ tused ], tsize - tused, "%02x", bchar ); assert( tsize > tused ); } } // add terminating null and append tused += sprintf_s( &fbuff[ tused ], tsize - tused, "\n" ); write_buff( fbuff, tused ); } return; } ike-2.2.1+dfsg/source/liblog/liblog.h000066400000000000000000000064051223036517100174010ustar00rootroot00000000000000/* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #ifndef _LOG_H_ #define _LOG_H_ #ifdef WIN32 # include # include # include #endif #ifdef UNIX # include # include # include # include # include "compat/winstring.h" #endif #include "libith.h" #include "export.h" #define LLOG_NONE 0 #define LLOG_ERROR 1 #define LLOG_INFO 2 #define LLOG_DEBUG 3 #define LLOG_LOUD 4 #define LLOG_DECODE 5 #define LOG_MAX_TXT ( 1024 * 2 ) #define LOG_MAX_BIN ( 1024 * 8 ) #define LOGFLAG_ECHO 0x01 #define LOGFLAG_SYSTEM 0x02 typedef struct DLX _LOG { private: #ifdef WIN32 #define snprintf _snprintf #define vsnprintf _vsnprintf HANDLE fp; #endif #ifdef UNIX FILE * fp; #endif ITH_LOCK lock; long log_level; long log_flags; bool write_buff( char * buff, size_t size ); bool write_line( char * buff, size_t size ); public: _LOG(); ~_LOG(); bool open( char * path, long level, long flags ); void close(); void txt( long level, const char * fmt, ... ); void bin( long level, long blevel, void * bin, size_t size, const char * fmt, ... ); }LOG, *PLOG; #endif ike-2.2.1+dfsg/source/libpfk/000077500000000000000000000000001223036517100157525ustar00rootroot00000000000000ike-2.2.1+dfsg/source/libpfk/CMakeLists.txt000066400000000000000000000015511223036517100205140ustar00rootroot00000000000000# # Shrew Soft VPN / PF KEY Helper Library # Cross Platform Make File # # author : Matthew Grooms # : mgrooms@shrew.net # : Copyright 2007, Shrew Soft Inc # include_directories( ${IKE_SOURCE_DIR}/source ${IKE_SOURCE_DIR}/source/libidb ${IKE_SOURCE_DIR}/source/libith ${IKE_SOURCE_DIR}/source/liblog ${INC_KERNEL_DIR} ) add_library( ss_pfk SHARED libpfk.cpp ) target_link_libraries( ss_pfk ss_idb ) set_target_properties( ss_pfk PROPERTIES VERSION ${RELVER} SOVERSION ${RELVER} ) if( APPLE ) set( MACOSX_BUNDLE_BUNDLE_NAME "ShrewSoftPfkey" ) set_property( TARGET ss_pfk PROPERTY FRAMEWORK ON ) set_property( TARGET ss_pfk PROPERTY OUTPUT_NAME ${MACOSX_BUNDLE_BUNDLE_NAME} ) endif( APPLE ) install( TARGETS ss_pfk LIBRARY DESTINATION ${PATH_LIB} FRAMEWORK DESTINATION "/Library/Frameworks" ) ike-2.2.1+dfsg/source/libpfk/libpfk.cpp000066400000000000000000001213451223036517100177330ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "libpfk.h" //============================================================================== // message class //============================================================================== bool _PFKI_MSG::local() { return ( ( long ) header.sadb_msg_pid == getpid() ); return false; } //============================================================================== // client interface class //============================================================================== #ifdef UNIX long _PFKI::send_message( PFKI_MSG & msg ) { if( conn == -1 ) return IPCERR_CLOSED; size_t msg_size = msg.size() + sizeof( sadb_msg ); msg.header.sadb_msg_len = ( u_int16_t ) PFKEY_UNIT64( msg_size ); msg.ins( &msg.header, sizeof( msg.header ) ); msg.size( msg_size ); return io_send( msg.buff(), msg_size ); } long _PFKI::recv_message( PFKI_MSG & msg ) { if( conn == -1 ) return IPCERR_CLOSED; fd_set fds; FD_ZERO( &fds ); FD_SET( conn, &fds ); FD_SET( conn_wake[ 0 ], &fds ); int max = conn_wake[ 0 ]; if( max < conn ) max = conn; if( select( max + 1, &fds, NULL, NULL, NULL ) <= 0 ) return IPCERR_FAILED; if( FD_ISSET( conn, &fds ) ) { msg.size( sizeof( sadb_msg ) ); size_t msg_size = msg.size(); long result = recv( conn, msg.buff(), msg_size, MSG_PEEK ); if( result < 0 ) return IPCERR_FAILED; if( result == 0 ) return IPCERR_CLOSED; msg.size( result ); msg.oset( 0 ); if( !msg.get( &msg.header, sizeof( sadb_msg ) ) ) return IPCERR_FAILED; msg_size = PFKEY_UNUNIT64( msg.header.sadb_msg_len ); msg.size( msg_size ); return io_recv( msg.buff(), msg_size ); } if( FD_ISSET( conn_wake[ 0 ], &fds ) ) { char c; recv( conn_wake[ 0 ], &c, 1, 0 ); return IPCERR_WAKEUP; } return IPCERR_NODATA; } long _PFKI::attach( long timeout ) { detach(); // // open our pfkey socket // conn = socket( PF_KEY, SOCK_RAW, PF_KEY_V2 ); if( conn < 0 ) return IPCERR_FAILED; // // set socket buffer size // const int buffsize = PFKEY_BUFFSIZE; setsockopt( conn, SOL_SOCKET, SO_SNDBUF, &buffsize, sizeof( buffsize ) ); setsockopt( conn, SOL_SOCKET, SO_RCVBUF, &buffsize, sizeof( buffsize ) ); // // set socket to non-blocking // if( fcntl( conn, F_SETFL, O_NONBLOCK ) == -1 ) return IPCERR_FAILED; return IPCERR_OK; } void _PFKI::wakeup() { ITH_IPCC::wakeup(); } void _PFKI::detach() { if( conn != -1 ) close( conn ); } #endif // // PFKI WIN32 Specific // #ifdef WIN32 long _PFKI::send_message( PFKI_MSG & msg ) { size_t msg_size = msg.size() + sizeof( sadb_msg ); msg.header.sadb_msg_len = ( u_int16_t ) PFKEY_UNIT64( msg_size ); msg.ins( &msg.header, sizeof( msg.header ) ); msg.size( msg_size ); return io_send( msg.buff(), msg_size ); } long _PFKI::recv_message( PFKI_MSG & msg ) { msg.size( sizeof( sadb_msg ) ); size_t msg_read = msg.size(); size_t msg_size = 0; long result = io_recv( msg.buff(), msg_read ); if( ( result == IPCERR_OK ) || ( result == IPCERR_BUFFER ) ) { msg.oset( 0 ); if( !msg.get( &msg.header, sizeof( sadb_msg ) ) ) return IPCERR_FAILED; msg_size = PFKEY_UNUNIT64( msg.header.sadb_msg_len ); msg.size( msg_size ); result = io_recv( msg.buff() + msg_read, msg_size - msg_read ); } return result; } long _PFKI::attach( long timeout ) { return ITH_IPCC::attach( PFKI_PIPE_NAME, timeout ); } void _PFKI::wakeup() { ITH_IPCC::wakeup(); } void _PFKI::detach() { ITH_IPCC::detach(); } #endif const char * _PFKI::name( long type, long value ) { static const char * unknown = "unknown"; switch( type ) { case NAME_MSGTYPE: { static const char * msgtype_00 = "RESERVED"; static const char * msgtype_01 = "GETSPI"; static const char * msgtype_02 = "UPDATE"; static const char * msgtype_03 = "ADD"; static const char * msgtype_04 = "DELETE"; static const char * msgtype_05 = "GET"; static const char * msgtype_06 = "ACQUIRE"; static const char * msgtype_07 = "REGISTER"; static const char * msgtype_08 = "EXPIRE"; static const char * msgtype_09 = "FLUSH"; static const char * msgtype_10 = "DUMP"; static const char * msgtype_11 = "X_PROMISC"; static const char * msgtype_12 = "X_PCHANGE"; static const char * msgtype_13 = "X_SPDUPDATE"; static const char * msgtype_14 = "X_SPDADD"; static const char * msgtype_15 = "X_SPDDELETE"; static const char * msgtype_16 = "X_SPDGET"; static const char * msgtype_17 = "X_SPDACQUIRE"; static const char * msgtype_18 = "X_SPDDUMP"; static const char * msgtype_19 = "X_SPDFLUSH"; static const char * msgtype_20 = "X_SPDSETIDX"; static const char * msgtype_21 = "X_SPDEXPIRE"; static const char * msgtype_22 = "X_SPDDELETE2"; // static const char * msgtype_23 = "X_NAT_T_NEW_MAPPING"; switch( value ) { case SADB_RESERVED: return msgtype_00; case SADB_GETSPI: return msgtype_01; case SADB_UPDATE: return msgtype_02; case SADB_ADD: return msgtype_03; case SADB_DELETE: return msgtype_04; case SADB_GET: return msgtype_05; case SADB_ACQUIRE: return msgtype_06; case SADB_REGISTER: return msgtype_07; case SADB_EXPIRE: return msgtype_08; case SADB_FLUSH: return msgtype_09; case SADB_DUMP: return msgtype_10; case SADB_X_PROMISC: return msgtype_11; case SADB_X_PCHANGE: return msgtype_12; case SADB_X_SPDUPDATE: return msgtype_13; case SADB_X_SPDADD: return msgtype_14; case SADB_X_SPDDELETE: return msgtype_15; case SADB_X_SPDGET: return msgtype_16; case SADB_X_SPDACQUIRE: return msgtype_17; case SADB_X_SPDDUMP: return msgtype_18; case SADB_X_SPDFLUSH: return msgtype_19; case SADB_X_SPDSETIDX: return msgtype_20; case SADB_X_SPDEXPIRE: return msgtype_21; case SADB_X_SPDDELETE2: return msgtype_22; // case SADB_X_NAT_T_NEW_MAPPING: // return msgtype_23; default: return unknown; } } case NAME_SAENCR: { static const char * encrtype_02 = "DES-CBC"; static const char * encrtype_03 = "3DES-CBC"; static const char * encrtype_06 = "CAST128-CBC"; static const char * encrtype_07 = "BLOWFISH-CBC"; static const char * encrtype_12 = "AES-CBC"; switch( value ) { case SADB_EALG_DESCBC: return encrtype_02; case SADB_EALG_3DESCBC: return encrtype_03; case SADB_X_EALG_CAST128CBC: return encrtype_06; case SADB_X_EALG_BLOWFISHCBC: return encrtype_07; case SADB_X_EALG_AESCBC: return encrtype_12; default: return unknown; } } case NAME_SACOMP: { static const char * comptype_01 = "OUI"; static const char * comptype_02 = "DEFLATE"; static const char * comptype_03 = "LZS"; switch( value ) { case SADB_X_CALG_OUI: return comptype_01; case SADB_X_CALG_DEFLATE: return comptype_02; case SADB_X_CALG_LZS: return comptype_03; default: return unknown; } } case NAME_SAAUTH: { static const char * authtype_02 = "HMAC-MD5"; static const char * authtype_03 = "HMAC-SHA1"; static const char * authtype_04 = "HMAC-SHA2-256"; static const char * authtype_05 = "HMAC-SHA2-384"; static const char * authtype_06 = "HMAC-SHA2-512"; switch( value ) { case SADB_AALG_MD5HMAC: return authtype_02; case SADB_AALG_SHA1HMAC: return authtype_03; case SADB_X_AALG_SHA2_256HMAC: return authtype_04; case SADB_X_AALG_SHA2_384HMAC: return authtype_05; case SADB_X_AALG_SHA2_512HMAC: return authtype_06; default: return unknown; } } case NAME_SATYPE: { static const char * satype_00 = "UNSPEC"; static const char * satype_02 = "AH"; static const char * satype_03 = "ESP"; static const char * satype_05 = "RSVP"; static const char * satype_06 = "OSPFV2"; static const char * satype_07 = "RIPV2"; static const char * satype_08 = "MIP"; static const char * satype_09 = "IPCOMP"; static const char * satype_11 = "TCPSIGNATURE"; switch( value ) { case SADB_SATYPE_UNSPEC: return satype_00; case SADB_SATYPE_AH: return satype_02; case SADB_SATYPE_ESP: return satype_03; case SADB_SATYPE_RSVP: return satype_05; case SADB_SATYPE_OSPFV2: return satype_06; case SADB_SATYPE_RIPV2: return satype_07; case SADB_SATYPE_MIP: return satype_08; case SADB_X_SATYPE_IPCOMP: return satype_09; // case SADB_X_SATYPE_TCPSIGNATURE: // return satype_11; default: return unknown; } } case NAME_SPMODE: { static const char * plcymode_00 = "ANY"; static const char * plcymode_01 = "TANSPORT"; static const char * plcymode_02 = "TUNNEL"; switch( value ) { case IPSEC_MODE_ANY: return plcymode_00; case IPSEC_MODE_TRANSPORT: return plcymode_01; case IPSEC_MODE_TUNNEL: return plcymode_02; default: return unknown; } } case NAME_SPTYPE: { static const char * plcytype_00 = "DISCARD"; static const char * plcytype_01 = "NONE"; static const char * plcytype_02 = "IPSEC"; static const char * plcytype_03 = "ENTRUST"; static const char * plcytype_04 = "BYPASS"; switch( value ) { case IPSEC_POLICY_DISCARD: return plcytype_00; case IPSEC_POLICY_NONE: return plcytype_01; case IPSEC_POLICY_IPSEC: return plcytype_02; case IPSEC_POLICY_ENTRUST: return plcytype_03; case IPSEC_POLICY_BYPASS: return plcytype_04; default: return unknown; } } case NAME_SPDIR: { static const char * plcydir_00 = "ANY"; static const char * plcydir_01 = "INBOUND"; static const char * plcydir_02 = "OUTBOUND"; static const char * plcydir_03 = "MAX"; static const char * plcydir_04 = "INVALID"; switch( value ) { case IPSEC_DIR_ANY: return plcydir_00; case IPSEC_DIR_INBOUND: return plcydir_01; case IPSEC_DIR_OUTBOUND: return plcydir_02; case IPSEC_DIR_MAX: return plcydir_03; case IPSEC_DIR_INVALID: return plcydir_04; default: return unknown; } } case NAME_SPLEVEL: { static const char * plcylevel_00 = "ANY"; static const char * plcylevel_01 = "USE"; static const char * plcylevel_02 = "REQUIRE"; static const char * plcylevel_03 = "UNIQUE"; switch( value ) { case IPSEC_LEVEL_DEFAULT: return plcylevel_00; case IPSEC_LEVEL_USE: return plcylevel_01; case IPSEC_LEVEL_REQUIRE: return plcylevel_02; case IPSEC_LEVEL_UNIQUE: return plcylevel_03; default: return unknown; } } case NAME_NTTYPE: { static const char * nattype_00 = "NONE"; static const char * nattype_01 = "ESPINUDP-NON-IKE"; static const char * nattype_02 = "ESPINUDP"; switch( value ) { case 0: return nattype_00; #ifdef OPT_NATT case UDP_ENCAP_ESPINUDP_NON_IKE: return nattype_01; case UDP_ENCAP_ESPINUDP: return nattype_02; #endif default: return unknown; } } } return unknown; } //============================================================================== // buffer management functions //============================================================================== bool _PFKI::sockaddr_len( int safam, int & salen ) { switch( safam ) { case AF_INET: salen = sizeof( sockaddr_in ); return true; } printf( "XX : address family %i unhandled\n", safam ); return false; } long _PFKI::buff_get_ext( PFKI_MSG & msg, sadb_ext ** ext, long type ) { unsigned char * buff = msg.buff(); size_t size = msg.size(); buff += sizeof( sadb_msg ); size -= sizeof( sadb_msg ); while( 1 ) { // // make sure the buffer holds // enough data to contain an // extension header // if( long( sizeof( sadb_ext ) ) > size ) { printf( "XX : extension not found\n" ); return IPCERR_FAILED; } sadb_ext * ext_head = ( sadb_ext * ) buff; // // make sure the buffer holds // enough data to contain the // extension body // if( PFKEY_EXTLEN( ext_head ) > size ) { printf( "XX : buffer too small for ext body ( %i bytes )\n", PFKEY_EXTLEN( ext_head ) ); return IPCERR_FAILED; } // // stop evaluation if this is // the requested extension // if( ext_head->sadb_ext_type == type ) { // // sainfo the pointers and size // *ext = ( sadb_ext * ) buff; break; } // // move to next extension // buff += PFKEY_EXTLEN( ext_head ); size -= PFKEY_EXTLEN( ext_head ); } return IPCERR_OK; } long _PFKI::buff_add_ext( PFKI_MSG & msg, sadb_ext ** ext, long xlen, bool unit64 ) { size_t oset = msg.size(); xlen = PFKEY_ALIGN8( xlen ); msg.add( 0, xlen ); *ext = ( sadb_ext * )( msg.buff() + oset ); if( unit64 ) ( *ext )->sadb_ext_len = ( u_int16_t ) PFKEY_UNIT64( xlen ); else ( *ext )->sadb_ext_len = ( u_int16_t ) xlen; return IPCERR_OK; } long _PFKI::buff_get_address( sadb_address * ext, PFKI_ADDR & addr ) { unsigned char * buff = ( unsigned char * ) ext; int size = PFKEY_UNUNIT64( ext->sadb_address_len ); addr.proto = ext->sadb_address_proto; addr.prefix = ext->sadb_address_prefixlen; buff += sizeof( sadb_address ); size -= sizeof( sadb_address ); sockaddr * saddr = ( sockaddr * ) buff; int salen; if( !sockaddr_len( saddr->sa_family, salen ) ) return IPCERR_FAILED; if( size < salen ) { printf( "!! : pfkey address size mismatch\n" ); return IPCERR_FAILED; } memcpy( &addr.saddr, saddr, salen ); return IPCERR_OK; } long _PFKI::buff_set_address( sadb_address * ext, PFKI_ADDR & addr ) { unsigned char * buff = ( unsigned char * ) ext; int size = PFKEY_UNUNIT64( ext->sadb_address_len ); ext->sadb_address_proto = addr.proto; ext->sadb_address_prefixlen = addr.prefix; buff += sizeof( sadb_address ); size -= sizeof( sadb_address ); int salen; if( !sockaddr_len( addr.saddr.sa_family, salen ) ) return IPCERR_FAILED; if( size < salen ) { printf( "!! : pfkey address size mismatch\n" ); return IPCERR_FAILED; } memcpy( buff, &addr.saddr, salen ); return IPCERR_OK; } long _PFKI::buff_set_key( sadb_key * ext, PFKI_KEY & key ) { unsigned char * buff = ( unsigned char * ) ext; int size = PFKEY_UNUNIT64( ext->sadb_key_len ); ext->sadb_key_bits = key.length * 8; buff += sizeof( sadb_key ); size -= sizeof( sadb_key ); if( size < key.length ) { printf( "!! : pfkey key size mismatch ( %i < %i )\n", size, key.length ); return IPCERR_FAILED; } assert( PFKI_MAX_KEYLEN >= key.length ); memcpy( buff, key.keydata, key.length ); return IPCERR_OK; } long _PFKI::buff_get_key( sadb_key * ext, PFKI_KEY & key ) { unsigned char * buff = ( unsigned char * ) ext; int size = PFKEY_UNUNIT64( ext->sadb_key_len ); buff += sizeof( sadb_key ); size -= sizeof( sadb_key ); if( !ext->sadb_key_bits ) return IPCERR_FAILED; key.length = ext->sadb_key_bits / 8; if( size < key.length ) { printf( "!! : pfkey key size mismatch ( %i < %i )\n", size, key.length ); return IPCERR_FAILED; } memcpy( key.keydata, buff, key.length ); return IPCERR_OK; } long _PFKI::buff_get_ipsec( sadb_x_policy * ext, PFKI_SPINFO & spinfo ) { unsigned char * buff = ( unsigned char * ) ext; int size = PFKEY_UNUNIT64( ext->sadb_x_policy_len ); buff += sizeof( sadb_x_policy ); size -= sizeof( sadb_x_policy ); long xindex = 0; while( size >= long( sizeof( sadb_x_ipsecrequest ) ) ) { sadb_x_ipsecrequest * ipsr = ( sadb_x_ipsecrequest * ) buff; if( xindex >= PFKI_MAX_XFORMS ) break; spinfo.xforms[ xindex ].proto = ipsr->sadb_x_ipsecrequest_proto; spinfo.xforms[ xindex ].mode = ipsr->sadb_x_ipsecrequest_mode; spinfo.xforms[ xindex ].level = ipsr->sadb_x_ipsecrequest_level; spinfo.xforms[ xindex ].reqid = ipsr->sadb_x_ipsecrequest_reqid; unsigned char * addr_buff = buff; long addr_size = size; addr_buff += sizeof( sadb_x_ipsecrequest ); addr_size -= sizeof( sadb_x_ipsecrequest ); if( addr_size >= 0 ) { sockaddr * saddr_src = ( sockaddr * )( addr_buff ); switch( saddr_src->sa_family ) { case AF_INET: { if( addr_size < long( sizeof( sockaddr_in ) ) ) break; memcpy( &spinfo.xforms[ xindex ].saddr_src, saddr_src, sizeof( sockaddr_in ) ); addr_buff += sizeof( sockaddr_in ); addr_size -= sizeof( sockaddr_in ); } } sockaddr * saddr_dst = ( sockaddr * )( addr_buff ); switch( saddr_dst->sa_family ) { case AF_INET: { if( addr_size < long( sizeof( sockaddr_in ) ) ) break; memcpy( &spinfo.xforms[ xindex ].saddr_dst, saddr_dst, sizeof( sockaddr_in ) ); addr_buff += sizeof( sockaddr_in ); addr_size -= sizeof( sockaddr_in ); } } } buff += ipsr->sadb_x_ipsecrequest_len; size -= ipsr->sadb_x_ipsecrequest_len; xindex++; } return IPCERR_OK; } long _PFKI::buff_add_ipsec( PFKI_MSG & msg, PFKI_SPINFO & spinfo ) { size_t size = sizeof( sadb_x_policy ); size_t oset = msg.size() - size; long result; long xindex = 0; while( spinfo.xforms[ xindex ].proto ) { if( xindex >= PFKI_MAX_XFORMS ) break; long ext_size = sizeof( sadb_x_ipsecrequest ); int salen_src = 0; int salen_dst = 0; if( spinfo.xforms[ xindex ].mode == IPSEC_MODE_TUNNEL ) { if( !sockaddr_len( spinfo.xforms[ xindex ].saddr_src.sa_family, salen_src ) ) return IPCERR_FAILED; if( !sockaddr_len( spinfo.xforms[ xindex ].saddr_dst.sa_family, salen_dst ) ) return IPCERR_FAILED; if( salen_src != salen_dst ) return IPCERR_FAILED; ext_size += ( salen_src + salen_dst ); } sadb_x_ipsecrequest * ipsr; result = buff_add_ext( msg, ( sadb_ext ** ) &ipsr, ext_size, false ); if( result != IPCERR_OK ) return result; ipsr->sadb_x_ipsecrequest_proto = spinfo.xforms[ xindex ].proto; ipsr->sadb_x_ipsecrequest_mode = spinfo.xforms[ xindex ].mode; ipsr->sadb_x_ipsecrequest_level = spinfo.xforms[ xindex ].level; ipsr->sadb_x_ipsecrequest_reqid = spinfo.xforms[ xindex ].reqid; unsigned char * ext_buff = ( unsigned char * ) ipsr; ext_buff += sizeof( sadb_x_ipsecrequest ); if( salen_src ) memcpy( ext_buff, &spinfo.xforms[ xindex ].saddr_src, salen_src ); ext_buff += salen_src; if( salen_dst ) memcpy( ext_buff, &spinfo.xforms[ xindex ].saddr_dst, salen_dst ); size += ext_size; xindex++; } // // reset the policy size // unsigned char * buff = msg.buff() + oset; sadb_x_policy * xpl = ( sadb_x_policy * ) buff; xpl->sadb_x_policy_len = ( u_int16_t ) PFKEY_UNIT64( size ); return IPCERR_OK; } //============================================================================== // message handler functions //============================================================================== long _PFKI::send_sainfo( u_int8_t sadb_msg_type, PFKI_SAINFO & sainfo, bool serv ) { PFKI_MSG msg; #if defined( OPT_NATT ) && defined( __APPLE__ ) sadb_sa_natt * xsa; #else sadb_sa * xsa; #endif sadb_x_sa2 * xsa2; sadb_address *xas, *xad; sadb_lifetime *xlh, *xls, *xlc; sadb_key *xke, *xka; sadb_spirange *xsr; long result; // // sa extension // switch( sadb_msg_type ) { case SADB_DUMP: case SADB_ADD: case SADB_GET: case SADB_DELETE: case SADB_GETSPI: case SADB_UPDATE: if( ( sadb_msg_type == SADB_DUMP ) && !serv ) break; if( ( sadb_msg_type == SADB_GETSPI ) && !serv ) break; #if defined( OPT_NATT ) && defined( __APPLE__ ) result = buff_add_ext( msg, ( sadb_ext ** ) &xsa, sizeof( sadb_sa_natt ) ); if( result != IPCERR_OK ) return result; xsa->sa.sadb_sa_exttype = SADB_EXT_SA; xsa->sa.sadb_sa_spi = sainfo.sa.spi; xsa->sa.sadb_sa_replay = sainfo.sa.replay; xsa->sa.sadb_sa_state = sainfo.sa.state; xsa->sa.sadb_sa_auth = sainfo.sa.auth; xsa->sa.sadb_sa_encrypt = sainfo.sa.encrypt; xsa->sa.sadb_sa_flags = sainfo.sa.flags; xsa->sadb_sa_natt_port = sainfo.sa.natt_port; #else result = buff_add_ext( msg, ( sadb_ext ** ) &xsa, sizeof( sadb_sa ) ); if( result != IPCERR_OK ) return result; xsa->sadb_sa_exttype = SADB_EXT_SA; xsa->sadb_sa_spi = sainfo.sa.spi; xsa->sadb_sa_replay = sainfo.sa.replay; xsa->sadb_sa_state = sainfo.sa.state; xsa->sadb_sa_auth = sainfo.sa.auth; xsa->sadb_sa_encrypt = sainfo.sa.encrypt; xsa->sadb_sa_flags = sainfo.sa.flags; #endif break; } if( sainfo.error ) goto sainfo_error; // // sa2 extension // switch( sadb_msg_type ) { case SADB_DUMP: case SADB_ADD: case SADB_GET: case SADB_GETSPI: case SADB_UPDATE: if( ( sadb_msg_type == SADB_DUMP ) && !serv ) break; if( ( sadb_msg_type == SADB_GET ) && !serv ) break; if( ( sadb_msg_type == SADB_GETSPI ) && serv ) break; result = buff_add_ext( msg, ( sadb_ext ** ) &xsa2, sizeof( sadb_x_sa2 ) ); if( result != IPCERR_OK ) return result; xsa2->sadb_x_sa2_exttype = SADB_X_EXT_SA2; xsa2->sadb_x_sa2_mode = sainfo.sa2.mode; xsa2->sadb_x_sa2_reqid = sainfo.sa2.reqid; xsa2->sadb_x_sa2_sequence = sainfo.sa2.sequence; break; } // // address extensions // switch( sadb_msg_type ) { case SADB_DUMP: case SADB_ADD: case SADB_GET: case SADB_DELETE: case SADB_GETSPI: case SADB_UPDATE: if( ( sadb_msg_type == SADB_DUMP ) && !serv ) break; if( ( sadb_msg_type == SADB_GET ) && !serv ) break; int salen_src; if( !sockaddr_len( sainfo.paddr_src.saddr.sa_family, salen_src ) ) return IPCERR_FAILED; result = buff_add_ext( msg, ( sadb_ext ** ) &xas, sizeof( sadb_address ) + salen_src ); if( result != IPCERR_OK ) return result; xas->sadb_address_exttype = SADB_EXT_ADDRESS_SRC; result = buff_set_address( xas, sainfo.paddr_src ); if( result != IPCERR_OK ) return result; int salen_dst; if( !sockaddr_len( sainfo.paddr_dst.saddr.sa_family, salen_dst ) ) return IPCERR_FAILED; result = buff_add_ext( msg, ( sadb_ext ** ) &xad, sizeof( sadb_address ) + salen_dst ); if( result != IPCERR_OK ) return result; xad->sadb_address_exttype = SADB_EXT_ADDRESS_DST; result = buff_set_address( xad, sainfo.paddr_dst ); if( result != IPCERR_OK ) return result; break; } // // soft and hard lifetime extensions // switch( sadb_msg_type ) { case SADB_DUMP: case SADB_ADD: case SADB_GET: case SADB_UPDATE: if( ( sadb_msg_type == SADB_DUMP ) && !serv ) break; if( ( sadb_msg_type == SADB_GET ) && !serv ) break; result = buff_add_ext( msg, ( sadb_ext ** ) &xlh, sizeof( sadb_lifetime ) ); if( result != IPCERR_OK ) return result; xlh->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD; xlh->sadb_lifetime_allocations = sainfo.ltime_hard.allocations; xlh->sadb_lifetime_bytes = sainfo.ltime_hard.bytes; xlh->sadb_lifetime_addtime = sainfo.ltime_hard.addtime; xlh->sadb_lifetime_usetime = sainfo.ltime_hard.usetime; result = buff_add_ext( msg, ( sadb_ext ** ) &xls, sizeof( sadb_lifetime ) ); if( result != IPCERR_OK ) return result; xls->sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT; xls->sadb_lifetime_allocations = sainfo.ltime_soft.allocations; xls->sadb_lifetime_bytes = sainfo.ltime_soft.bytes; xls->sadb_lifetime_addtime = sainfo.ltime_soft.addtime; xls->sadb_lifetime_usetime = sainfo.ltime_soft.usetime; break; } // // current lifetime extension // switch( sadb_msg_type ) { case SADB_DUMP: case SADB_ADD: case SADB_GET: case SADB_UPDATE: if( ( sadb_msg_type == SADB_DUMP ) && !serv ) break; if( ( sadb_msg_type == SADB_GET ) && !serv ) break; result = buff_add_ext( msg, ( sadb_ext ** ) &xlc, sizeof( sadb_lifetime ) ); if( result != IPCERR_OK ) return result; xlc->sadb_lifetime_exttype = SADB_EXT_LIFETIME_CURRENT; xlc->sadb_lifetime_allocations = sainfo.ltime_curr.allocations; xlc->sadb_lifetime_bytes = sainfo.ltime_curr.bytes; xlc->sadb_lifetime_addtime = sainfo.ltime_curr.addtime; xlc->sadb_lifetime_usetime = sainfo.ltime_curr.usetime; break; } // // key data extension // switch( sadb_msg_type ) { case SADB_DUMP: case SADB_ADD: case SADB_GET: case SADB_UPDATE: if( ( sadb_msg_type == SADB_DUMP ) && !serv ) break; if( ( sadb_msg_type == SADB_GET ) && !serv ) break; if( sainfo.ekey.length ) { result = buff_add_ext( msg, ( sadb_ext ** ) &xke, sizeof( sadb_key ) + sainfo.ekey.length ); if( result != IPCERR_OK ) return result; xke->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT; result = buff_set_key( xke, sainfo.ekey ); if( result != IPCERR_OK ) return result; } if( sainfo.akey.length ) { result = buff_add_ext( msg, ( sadb_ext ** ) &xka, sizeof( sadb_key ) + sainfo.akey.length ); if( result != IPCERR_OK ) return result; xka->sadb_key_exttype = SADB_EXT_KEY_AUTH; result = buff_set_key( xka, sainfo.akey ); if( result != IPCERR_OK ) return result; } break; } #if defined( OPT_NATT ) && !defined( __APPLE__ ) // // natt extension // switch( sadb_msg_type ) { case SADB_DUMP: case SADB_ADD: case SADB_GET: case SADB_UPDATE: if( ( sadb_msg_type == SADB_DUMP ) && !serv ) break; if( ( sadb_msg_type == SADB_GET ) && !serv ) break; if( sainfo.natt.type ) { sadb_x_nat_t_type *xnt; sadb_x_nat_t_port *xnps, *xnpd; result = buff_add_ext( msg, ( sadb_ext ** ) &xnt, sizeof( sadb_x_nat_t_type ) ); if( result != IPCERR_OK ) return result; xnt->sadb_x_nat_t_type_exttype = SADB_X_EXT_NAT_T_TYPE; xnt->sadb_x_nat_t_type_type = sainfo.natt.type; result = buff_add_ext( msg, ( sadb_ext ** ) &xnps, sizeof( sadb_x_nat_t_port ) ); if( result != IPCERR_OK ) return result; xnps->sadb_x_nat_t_port_exttype = SADB_X_EXT_NAT_T_SPORT; xnps->sadb_x_nat_t_port_port = sainfo.natt.port_src; result = buff_add_ext( msg, ( sadb_ext ** ) &xnpd, sizeof( sadb_x_nat_t_port ) ); if( result != IPCERR_OK ) return result; xnpd->sadb_x_nat_t_port_exttype = SADB_X_EXT_NAT_T_DPORT; xnpd->sadb_x_nat_t_port_port = sainfo.natt.port_dst; } break; } #endif // // spi range extension // switch( sadb_msg_type ) { case SADB_GETSPI: if( sainfo.range.min || sainfo.range.max ) { result = buff_add_ext( msg, ( sadb_ext ** ) &xsr, sizeof( sadb_spirange ) ); if( result != IPCERR_OK ) return result; xsr->sadb_spirange_exttype = SADB_EXT_SPIRANGE; xsr->sadb_spirange_min = sainfo.range.min; xsr->sadb_spirange_max = sainfo.range.max; } break; } sainfo_error: if( !serv ) sainfo.pid = getpid(); msg.header.sadb_msg_version = PF_KEY_V2; msg.header.sadb_msg_type = sadb_msg_type; msg.header.sadb_msg_errno = sainfo.error; msg.header.sadb_msg_satype = sainfo.satype; msg.header.sadb_msg_reserved = 0; msg.header.sadb_msg_seq = sainfo.seq; msg.header.sadb_msg_pid = sainfo.pid; return send_message( msg ); } long _PFKI::send_spinfo( u_int8_t sadb_msg_type, PFKI_SPINFO & spinfo, bool serv ) { PFKI_MSG msg; sadb_x_policy * xpl; sadb_address *xas, *xad; long result; if( spinfo.error ) goto spinfo_error; // // sp extension // switch( sadb_msg_type ) { case SADB_ACQUIRE: case SADB_X_SPDDUMP: case SADB_X_SPDADD: case SADB_X_SPDDELETE2: if( ( sadb_msg_type == SADB_X_SPDDUMP ) && !serv ) break; result = buff_add_ext( msg, ( sadb_ext ** ) &xpl, sizeof( sadb_x_policy ) ); if( result != IPCERR_OK ) return result; xpl->sadb_x_policy_exttype = SADB_X_EXT_POLICY; xpl->sadb_x_policy_type = spinfo.sp.type; xpl->sadb_x_policy_id = spinfo.sp.id; xpl->sadb_x_policy_dir = spinfo.sp.dir; if( spinfo.sp.type == IPSEC_POLICY_IPSEC ) { result = buff_add_ipsec( msg, spinfo ); if( result != IPCERR_OK ) return result; } break; } // // address extensions // switch( sadb_msg_type ) { case SADB_ACQUIRE: case SADB_X_SPDDUMP: case SADB_X_SPDADD: if( ( sadb_msg_type == SADB_X_SPDDUMP ) && !serv ) break; int salen_src; if( !sockaddr_len( spinfo.paddr_src.saddr.sa_family, salen_src ) ) return IPCERR_FAILED; result = buff_add_ext( msg, ( sadb_ext ** ) &xas, sizeof( sadb_address ) + salen_src ); if( result != IPCERR_OK ) return result; xas->sadb_address_exttype = SADB_EXT_ADDRESS_SRC; result = buff_set_address( xas, spinfo.paddr_src ); if( result != IPCERR_OK ) return result; int salen_dst; if( !sockaddr_len( spinfo.paddr_dst.saddr.sa_family, salen_dst ) ) return IPCERR_FAILED; result = buff_add_ext( msg, ( sadb_ext ** ) &xad, sizeof( sadb_address ) + salen_dst ); if( result != IPCERR_OK ) return result; xad->sadb_address_exttype = SADB_EXT_ADDRESS_DST; result = buff_set_address( xad, spinfo.paddr_dst ); if( result != IPCERR_OK ) return result; break; } spinfo_error: if( !serv ) spinfo.pid = getpid(); msg.header.sadb_msg_version = PF_KEY_V2; msg.header.sadb_msg_type = sadb_msg_type; msg.header.sadb_msg_errno = spinfo.error; msg.header.sadb_msg_satype = SADB_SATYPE_UNSPEC; msg.header.sadb_msg_reserved = 0; msg.header.sadb_msg_seq = spinfo.seq; msg.header.sadb_msg_pid = spinfo.pid; return send_message( msg ); } // // extension functions // long _PFKI::read_sa( PFKI_MSG & msg, PFKI_SA & sa ) { // // read policy extension // sadb_sa * xsa; long result = buff_get_ext( msg, ( sadb_ext ** ) &xsa, SADB_EXT_SA ); if( result != IPCERR_OK ) return result; sa.spi = xsa->sadb_sa_spi; sa.replay = xsa->sadb_sa_replay; sa.state = xsa->sadb_sa_state; sa.auth = xsa->sadb_sa_auth; sa.encrypt = xsa->sadb_sa_encrypt; sa.flags = xsa->sadb_sa_flags; return IPCERR_OK; } long _PFKI::read_sa2( PFKI_MSG & msg, PFKI_SA2 & sa2 ) { // // read policy extension // sadb_x_sa2 * xsa2; long result = buff_get_ext( msg, ( sadb_ext ** ) &xsa2, SADB_X_EXT_SA2 ); if( result != IPCERR_OK ) return result; sa2.mode = xsa2->sadb_x_sa2_mode; sa2.sequence = xsa2->sadb_x_sa2_sequence; sa2.reqid = xsa2->sadb_x_sa2_reqid; return true; } long _PFKI::read_range( PFKI_MSG & msg, PFKI_RANGE & range ) { // // read address extension // sadb_spirange * xsr; long result; result = buff_get_ext( msg, ( sadb_ext ** ) &xsr, SADB_EXT_SPIRANGE ); if( result != IPCERR_OK ) return result; range.min = xsr->sadb_spirange_min; range.max = xsr->sadb_spirange_max; return IPCERR_OK; } long _PFKI::read_ltime_curr( PFKI_MSG & msg, PFKI_LTIME & ltime ) { // // read lifetime extension // sadb_lifetime * xlt; long result; result = buff_get_ext( msg, ( sadb_ext ** ) &xlt, SADB_EXT_LIFETIME_CURRENT ); if( result != IPCERR_OK ) return result; ltime.allocations = xlt->sadb_lifetime_allocations; ltime.addtime = xlt->sadb_lifetime_addtime; ltime.usetime = xlt->sadb_lifetime_usetime; ltime.bytes = xlt->sadb_lifetime_bytes; return IPCERR_OK; } long _PFKI::read_ltime_hard( PFKI_MSG & msg, PFKI_LTIME & ltime ) { // // read lifetime extension // sadb_lifetime * xlt; long result; result = buff_get_ext( msg, ( sadb_ext ** ) &xlt, SADB_EXT_LIFETIME_HARD ); if( result != IPCERR_OK ) return result; ltime.allocations = xlt->sadb_lifetime_allocations; ltime.addtime = xlt->sadb_lifetime_addtime; ltime.usetime = xlt->sadb_lifetime_usetime; ltime.bytes = xlt->sadb_lifetime_bytes; return IPCERR_OK; } long _PFKI::read_ltime_soft( PFKI_MSG & msg, PFKI_LTIME & ltime ) { // // read lifetime extension // sadb_lifetime * xlt; long result; result = buff_get_ext( msg, ( sadb_ext ** ) &xlt, SADB_EXT_LIFETIME_SOFT ); if( result != IPCERR_OK ) return result; ltime.allocations = xlt->sadb_lifetime_allocations; ltime.addtime = xlt->sadb_lifetime_addtime; ltime.usetime = xlt->sadb_lifetime_usetime; ltime.bytes = xlt->sadb_lifetime_bytes; return IPCERR_OK; } long _PFKI::read_key_a( PFKI_MSG & msg, PFKI_KEY & akey ) { // // read key extension // sadb_key * xka; long result; result = buff_get_ext( msg, ( sadb_ext ** ) &xka, SADB_EXT_KEY_AUTH ); if( result != IPCERR_OK ) return result; result = buff_get_key( xka, akey ); if( result != IPCERR_OK ) return result; return IPCERR_OK; } long _PFKI::read_key_e( PFKI_MSG & msg, PFKI_KEY & ekey ) { // // read key extension // sadb_key * xke; long result; result = buff_get_ext( msg, ( sadb_ext ** ) &xke, SADB_EXT_KEY_ENCRYPT ); if( result != IPCERR_OK ) return result; result = buff_get_key( xke, ekey ); if( result != IPCERR_OK ) return result; return IPCERR_OK; } long _PFKI::read_address_src( PFKI_MSG & msg, PFKI_ADDR & addr ) { // // read address extension // sadb_address * xad; long result; result = buff_get_ext( msg, ( sadb_ext ** ) &xad, SADB_EXT_ADDRESS_SRC ); if( result != IPCERR_OK ) return result; result = buff_get_address( xad, addr ); if( result != IPCERR_OK ) return result; return IPCERR_OK; } long _PFKI::read_address_dst( PFKI_MSG & msg, PFKI_ADDR & addr ) { // // read address extension // sadb_address * xad; long result; result = buff_get_ext( msg, ( sadb_ext ** ) &xad, SADB_EXT_ADDRESS_DST ); if( result != IPCERR_OK ) return result; result = buff_get_address( xad, addr ); if( result != IPCERR_OK ) return result; return IPCERR_OK; } #if defined( OPT_NATT ) && !defined( __APPLE__ ) long _PFKI::read_natt( PFKI_MSG & msg, PFKI_NATT & natt ) { sadb_x_nat_t_type * xnt; sadb_x_nat_t_port * xnps, * xnpd; long result; result = buff_get_ext( msg, ( sadb_ext ** ) &xnt, SADB_X_EXT_NAT_T_TYPE ); if( result != IPCERR_OK ) return result; natt.type = xnt->sadb_x_nat_t_type_type; result = buff_get_ext( msg, ( sadb_ext ** ) &xnps, SADB_X_EXT_NAT_T_SPORT ); if( result != IPCERR_OK ) return result; natt.port_src = xnps->sadb_x_nat_t_port_port; result = buff_get_ext( msg, ( sadb_ext ** ) &xnpd, SADB_X_EXT_NAT_T_DPORT ); if( result != IPCERR_OK ) return result; natt.port_dst = xnpd->sadb_x_nat_t_port_port; return IPCERR_OK; } # endif // OPT_NATT && !__APPLE__ long _PFKI::read_policy( PFKI_MSG & msg, PFKI_SPINFO & spinfo ) { // // read policy extension // sadb_x_policy * xpl; long result; result = buff_get_ext( msg, ( sadb_ext ** ) &xpl, SADB_X_EXT_POLICY ); if( result != IPCERR_OK ) return result; spinfo.sp.type = xpl->sadb_x_policy_type; spinfo.sp.id = xpl->sadb_x_policy_id; spinfo.sp.dir = xpl->sadb_x_policy_dir; if( spinfo.sp.type == IPSEC_POLICY_IPSEC ) { result = buff_get_ipsec( xpl, spinfo ); if( result != IPCERR_OK ) return result; } return IPCERR_OK; } // // client functions // long _PFKI::send_register( u_int8_t satype ) { PFKI_SAINFO sainfo; memset( &sainfo, 0, sizeof( sainfo ) ); sainfo.satype = satype; return send_sainfo( SADB_REGISTER, sainfo, false ); } long _PFKI::send_dump() { PFKI_SAINFO sainfo; memset( &sainfo, 0, sizeof( sainfo ) ); return send_sainfo( SADB_DUMP, sainfo, false ); } long _PFKI::send_add( PFKI_SAINFO & sainfo ) { return send_sainfo( SADB_ADD, sainfo, false ); } long _PFKI::send_get( PFKI_SAINFO & sainfo ) { return send_sainfo( SADB_GET, sainfo, false ); } long _PFKI::send_del( PFKI_SAINFO & sainfo ) { return send_sainfo( SADB_DELETE, sainfo, false ); } long _PFKI::send_getspi( PFKI_SAINFO & sainfo ) { return send_sainfo( SADB_GETSPI, sainfo, false ); } long _PFKI::send_update( PFKI_SAINFO & sainfo ) { return send_sainfo( SADB_UPDATE, sainfo, false ); } long _PFKI::send_spdump() { PFKI_SPINFO spinfo; memset( &spinfo, 0, sizeof( spinfo ) ); return send_spinfo( SADB_X_SPDDUMP, spinfo, false ); } long _PFKI::send_spadd( PFKI_SPINFO & spinfo ) { return send_spinfo( SADB_X_SPDADD, spinfo, false ); } long _PFKI::send_spdel( PFKI_SPINFO & spinfo ) { return send_spinfo( SADB_X_SPDDELETE2, spinfo, false ); } // // server functions // long _PFKI::serv_dump( PFKI_SAINFO & sainfo ) { return send_sainfo( SADB_DUMP, sainfo, true ); } long _PFKI::serv_add( PFKI_SAINFO & sainfo ) { return send_sainfo( SADB_ADD, sainfo, true ); } long _PFKI::serv_get( PFKI_SAINFO & sainfo ) { return send_sainfo( SADB_GET, sainfo, true ); } long _PFKI::serv_del( PFKI_SAINFO & sainfo ) { return send_sainfo( SADB_DELETE, sainfo, true ); } long _PFKI::serv_acquire( PFKI_SPINFO & spinfo ) { return send_spinfo( SADB_ACQUIRE, spinfo, true ); } long _PFKI::serv_getspi( PFKI_SAINFO & sainfo ) { return send_sainfo( SADB_GETSPI, sainfo, true ); } long _PFKI::serv_update( PFKI_SAINFO & sainfo ) { return send_sainfo( SADB_UPDATE, sainfo, true ); } long _PFKI::serv_spdump( PFKI_SPINFO & spinfo ) { return send_spinfo( SADB_X_SPDDUMP, spinfo, true ); } long _PFKI::serv_spadd( PFKI_SPINFO & spinfo ) { return send_spinfo( SADB_X_SPDADD, spinfo, true ); } long _PFKI::serv_spdel( PFKI_SPINFO & spinfo ) { return send_spinfo( SADB_X_SPDDELETE2, spinfo, true ); } //============================================================================== // server interface class //============================================================================== #ifdef WIN32 long _PFKS::init() { return ITH_IPCS::init( PFKI_PIPE_NAME, true ); } void _PFKS::done() { ITH_IPCS::done(); } long _PFKS::inbound( PFKI ** pfki ) { IPCCONN ipcconn; long result = ITH_IPCS::inbound( PFKI_PIPE_NAME, ipcconn ); if( result == IPCERR_OK ) { *pfki = new PFKI; if( *pfki == NULL ) return IPCERR_FAILED; (*pfki)->io_conf( ipcconn ); } return result; } void _PFKS::wakeup() { ITH_IPCS::wakeup(); } #endif ike-2.2.1+dfsg/source/libpfk/libpfk.h000066400000000000000000000244011223036517100173730ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #ifndef _LIBPFK_H_ #define _LIBPFK_H_ #ifdef WIN32 # include # include # include # include # include "inttypes.h" # include "pfkeyv2.h" # include "ipsec.h" #endif #ifdef UNIX # ifdef __linux__ # include # include # include # include # include # include # include # include # include # include # else # include # include # include # include # include # include # include # include # ifdef OPT_NETIPSEC # include # else # include # endif # endif #endif #include "libidb.h" #include "libith.h" // // Win32 specific // #ifdef WIN32 #define PFKI_EVENT_NAME "pfki" #define PFKI_PIPE_NAME "\\\\.\\pipe\\pfki" #define getpid _getpid #endif // // Unix specific // #ifdef UNIX #define PFKEY_BUFFSIZE 128 * 1024 #ifndef SADB_X_EALG_AESCBC # define SADB_X_EALG_AESCBC 12 #endif #ifndef SADB_X_EALG_CAST128CBC # define SADB_X_EALG_CAST128CBC 6 #endif #ifndef SADB_X_AALG_SHA2_256HMAC # define SADB_X_AALG_SHA2_256HMAC SADB_X_AALG_SHA2_256 #endif #ifndef SADB_X_AALG_SHA2_384HMAC # define SADB_X_AALG_SHA2_384HMAC SADB_X_AALG_SHA2_384 #endif #ifndef SADB_X_AALG_SHA2_512HMAC # define SADB_X_AALG_SHA2_512HMAC SADB_X_AALG_SHA2_512 #endif # ifndef __FreeBSD__ // Linux and NetBSD compat #define PFKEY_SOFT_LIFETIME_RATE 80 #define PFKEY_UNUNIT64(a) ((a) << 3) #define PFKEY_UNIT64(a) ((a) >> 3) #define PFKEY_ALIGN8(a) (1 + (((a) - 1) | (8 - 1))) #define PFKEY_EXTLEN(msg) \ PFKEY_UNUNIT64(((struct sadb_ext *)(msg))->sadb_ext_len) #define PFKEY_ADDR_PREFIX(ext) \ (((struct sadb_address *)(ext))->sadb_address_prefixlen) #define PFKEY_ADDR_PROTO(ext) \ (((struct sadb_address *)(ext))->sadb_address_proto) #define PFKEY_ADDR_SADDR(ext) \ ((struct sockaddr *)((caddr_t)(ext) + sizeof(struct sadb_address))) # endif // __FreeBSD__ # ifdef __APPLE__ # endif // __APPLE__ #endif // UNIX // // these socket options are required for NAT-T // but not always defined in userland headers // #ifdef OPT_NATT #ifndef SOL_UDP #define SOL_UDP 17 #endif #ifndef UDP_ENCAP #define UDP_ENCAP 100 #endif #ifndef UDP_ENCAP_ESPINUDP_NON_IKE #define UDP_ENCAP_ESPINUDP_NON_IKE 1 #endif #ifndef UDP_ENCAP_ESPINUDP #define UDP_ENCAP_ESPINUDP 2 #endif #ifdef __APPLE__ #define SADB_X_EXT_NATT 2 #define SADB_X_EXT_NATT_KEEPALIVE 4 struct sadb_sa_natt { struct sadb_sa sa; u_int16_t sadb_sa_natt_port; u_int16_t sadb_reserved0; u_int32_t sadb_reserved1; }; #endif #endif // OPT_NATT // // common to all platforms // #include #include "export.h" #define PFKI_MAX_XFORMS 4 #define PFKI_MAX_KEYLEN 128 #define NAME_MSGTYPE 1 #define NAME_SATYPE 2 #define NAME_SAENCR 3 #define NAME_SACOMP 4 #define NAME_SAAUTH 5 #define NAME_SPTYPE 6 #define NAME_SPDIR 7 #define NAME_SPMODE 8 #define NAME_SPLEVEL 9 #define NAME_NTTYPE 10 #define PFKI_WINDSIZE 4 typedef struct _PFKI_SA { u_int32_t spi; u_int8_t replay; u_int8_t state; u_int8_t auth; u_int8_t encrypt; u_int32_t flags; #if defined( OPT_NATT ) && defined( __APPLE__ ) u_int16_t natt_port; #endif }PFKI_SA; typedef struct _PFKI_SA2 { u_int8_t mode; u_int32_t sequence; u_int32_t reqid; }PFKI_SA2; typedef struct _PFKI_ADDR { u_int8_t proto; u_int8_t prefix; union { sockaddr saddr; sockaddr_in saddr4; }; }PFKI_ADDR; typedef struct _PFKI_LTIME { u_int32_t allocations; u_int64_t bytes; u_int64_t addtime; u_int64_t usetime; }PFKI_LTIME; typedef struct _PFKI_KEY { u_int8_t keydata[ PFKI_MAX_KEYLEN ]; u_int16_t length; }PFKI_KEY; typedef struct _PFKI_RANGE { u_int32_t min; u_int32_t max; }PFKI_RANGE; typedef struct _PFKI_SP { u_int16_t type; u_int32_t id; u_int8_t dir; u_int8_t prot; u_int16_t port; }PFKI_SP; #if defined( OPT_NATT ) && !defined( __APPLE__ ) typedef struct _PFKI_NATT { u_int8_t type; u_int16_t port_src; u_int16_t port_dst; u_int16_t fraglen; }PFKI_NATT; #endif typedef struct _PFKI_SAINFO { u_int8_t satype; u_int32_t seq; u_int32_t pid; u_int8_t error; PFKI_SA sa; PFKI_SA2 sa2; PFKI_ADDR paddr_src; PFKI_ADDR paddr_dst; PFKI_LTIME ltime_curr; PFKI_LTIME ltime_hard; PFKI_LTIME ltime_soft; PFKI_KEY ekey; PFKI_KEY akey; PFKI_RANGE range; #if defined( OPT_NATT ) && !defined( __APPLE__ ) PFKI_NATT natt; #endif }PFKI_SAINFO; typedef struct _PFKI_XFORM { u_int16_t proto; u_int8_t mode; u_int8_t level; u_int16_t reqid; sockaddr saddr_src; sockaddr saddr_dst; }PFKI_XFORM; typedef struct _PFKI_SPINFO { u_int32_t seq; u_int32_t pid; u_int8_t error; PFKI_SP sp; PFKI_ADDR paddr_src; PFKI_ADDR paddr_dst; PFKI_XFORM xforms[ PFKI_MAX_XFORMS ]; }PFKI_SPINFO; typedef class DLX _PFKI_MSG : public BDATA { friend class _PFKI; public: sadb_msg header; bool local(); }PFKI_MSG; typedef class DLX _PFKI : private _ITH_IPCC, public IDB_ENTRY { friend class _PFKS; private: bool sockaddr_len( int safam, int & salen ); long buff_get_ext( PFKI_MSG & msg, sadb_ext ** ext, long type ); long buff_add_ext( PFKI_MSG & msg, sadb_ext ** ext, long xlen, bool unit64 = true ); long buff_get_address( sadb_address * ext, PFKI_ADDR & addr ); long buff_set_address( sadb_address * ext, PFKI_ADDR & addr ); long buff_get_ipsec( sadb_x_policy * ext, PFKI_SPINFO & spinfo ); long buff_add_ipsec( PFKI_MSG & msg, PFKI_SPINFO & spinfo ); long buff_get_key( sadb_key * ext, PFKI_KEY & key ); long buff_set_key( sadb_key * ext, PFKI_KEY & key ); long send_sainfo( u_int8_t sadb_msg_type, PFKI_SAINFO & sainfo, bool serv ); long send_spinfo( u_int8_t sadb_msg_type, PFKI_SPINFO & spinfo, bool serv ); public: // extention functions long read_sa( PFKI_MSG & msg, PFKI_SA & sa ); long read_sa2( PFKI_MSG & msg, PFKI_SA2 & sa2 ); long read_range( PFKI_MSG & msg, PFKI_RANGE & range ); long read_ltime_curr( PFKI_MSG & msg, PFKI_LTIME & ltime ); long read_ltime_hard( PFKI_MSG & msg, PFKI_LTIME & ltime ); long read_ltime_soft( PFKI_MSG & msg, PFKI_LTIME & ltime ); long read_key_a( PFKI_MSG & msg, PFKI_KEY & akey ); long read_key_e( PFKI_MSG & msg, PFKI_KEY & ekey ); long read_address_src( PFKI_MSG & msg, PFKI_ADDR & addr ); long read_address_dst( PFKI_MSG & msg, PFKI_ADDR & addr ); long read_policy( PFKI_MSG & msg, PFKI_SPINFO & spinfo ); #if defined( OPT_NATT ) && !defined( __APPLE__ ) long read_natt( PFKI_MSG & msg, PFKI_NATT & natt ); #endif const char * name( long type, long value ); long attach( long timeout ); void wakeup(); void detach(); long recv_message( PFKI_MSG & msg ); long send_message( PFKI_MSG & msg ); // client functions long send_register( u_int8_t satype ); long send_flush(); long send_dump(); long send_add( PFKI_SAINFO & sainfo ); long send_get( PFKI_SAINFO & sainfo ); long send_del( PFKI_SAINFO & sainfo ); long send_getspi( PFKI_SAINFO & sainfo ); long send_update( PFKI_SAINFO & sainfo ); long send_spflush(); long send_spdump(); long send_spadd( PFKI_SPINFO & spinfo ); long send_spdel( PFKI_SPINFO & spinfo ); // server functions long serv_dump( PFKI_SAINFO & sainfo ); long serv_add( PFKI_SAINFO & sainfo ); long serv_get( PFKI_SAINFO & sainfo ); long serv_del( PFKI_SAINFO & sainfo ); long serv_acquire( PFKI_SPINFO & spinfo ); long serv_getspi( PFKI_SAINFO & sainfo ); long serv_update( PFKI_SAINFO & sainfo ); long serv_spdump( PFKI_SPINFO & spinfo ); long serv_spadd( PFKI_SPINFO & spinfo ); long serv_spdel( PFKI_SPINFO & spinfo ); }PFKI; #ifdef WIN32 typedef class DLX _PFKS : private _ITH_IPCS { public: long init(); void done(); long inbound( PFKI ** pfki ); void wakeup(); }PFKS; #endif #endif ike-2.2.1+dfsg/source/libqt/000077500000000000000000000000001223036517100156165ustar00rootroot00000000000000ike-2.2.1+dfsg/source/libqt/CMakeLists.txt000066400000000000000000000044541223036517100203650ustar00rootroot00000000000000# # Shrew Soft VPN / QT Private Libs # Cross Platform Make File # # author : Matthew Grooms # : mgrooms@shrew.net # : Copyright 2007, Shrew Soft Inc # if( APPLE ) # QtCore Private Library Framework install( DIRECTORY "${QT_LIBRARY_DIR}/QtCore.framework/Contents" DESTINATION "/Library/Frameworks/ShrewSoftQtCore.framework" COMPONENT Runtime ) install( FILES "${QT_LIBRARY_DIR}/QtCore.framework/Versions/4/QtCore" DESTINATION "/Library/Frameworks/ShrewSoftQtCore.framework/Versions/4" RENAME "ShrewSoftQtCore" COMPONENT Runtime ) install( CODE "execute_process( COMMAND \"ln\" -s 4 /Library/Frameworks/ShrewSoftQtCore.framework/Versions/Current )" ) install( CODE "execute_process( COMMAND \"ln\" -s Versions/4/Resources /Library/Frameworks/ShrewSoftQtCore.framework/Resources )" ) install( CODE "execute_process( COMMAND \"install_name_tool\" -id ShrewSoftQtCore.framework/Versions/4/ShrewSoftQtCore /Library/Frameworks/ShrewSoftQtCore.framework/Versions/4/ShrewSoftQtCore )" ) # QtGui Private Library Framework install( DIRECTORY "${QT_LIBRARY_DIR}/QtGui.framework/Contents" DESTINATION "${QT_LIBRARY_DIR}/ShrewSoftQtGui.framework" COMPONENT Runtime ) install( FILES "${QT_LIBRARY_DIR}/QtGui.framework/Versions/4/QtGui" DESTINATION "/Library/Frameworks/ShrewSoftQtGui.framework/Versions/4" RENAME "ShrewSoftQtGui" COMPONENT Runtime ) install( CODE "execute_process( COMMAND \"ln\" -s 4 /Library/Frameworks/ShrewSoftQtGui.framework/Versions/Current )" ) install( CODE "execute_process( COMMAND \"ln\" -s Versions/4/Resources /Library/Frameworks/ShrewSoftQtGui.framework/Resources )" ) install( DIRECTORY "${QT_LIBRARY_DIR}/QtGui.framework/Versions/4/Resources" DESTINATION "/Library/Frameworks/ShrewSoftQtGui.framework/Versions/4" COMPONENT Runtime ) install( CODE "execute_process( COMMAND \"install_name_tool\" -id ShrewSoftQtGui.framework/Versions/4/ShrewSoftQtGui /Library/Frameworks/ShrewSoftQtGui.framework/Versions/4/ShrewSoftQtGui )" ) install( CODE "execute_process( COMMAND \"install_name_tool\" -change ${QT_LIBRARY_DIR}/QtCore.framework/Versions/4/QtCore ShrewSoftQtCore.framework/Versions/4/ShrewSoftQtCore /Library/Frameworks/ShrewSoftQtGui.framework/Versions/4/ShrewSoftQtGui )" ) endif( APPLE ) ike-2.2.1+dfsg/source/qikea/000077500000000000000000000000001223036517100155755ustar00rootroot00000000000000ike-2.2.1+dfsg/source/qikea/CMakeLists.txt000066400000000000000000000057021223036517100203410ustar00rootroot00000000000000# # Shrew Soft VPN / Access Manager Application # Cross Platform Make File # # author : Matthew Grooms # : mgrooms@shrew.net # : Copyright 2007, Shrew Soft Inc # include_directories( ${IKE_SOURCE_DIR}/source/ ${IKE_SOURCE_DIR}/source/ikec ${IKE_SOURCE_DIR}/source/libike ${IKE_SOURCE_DIR}/source/libidb ${IKE_SOURCE_DIR}/source/libith ${IKE_SOURCE_DIR}/source/liblog ${QT_INCLUDES} ) link_directories( ${IKE_SOURCE_DIR}/source/libip ${QT_LIBRARY_DIR} ) include( ${QT_USE_FILE} ) qt4_wrap_ui( UIH_FILES about.ui conflict.ui root.ui site.ui topology.ui ) qt4_wrap_cpp( CXX_FILES qikea.h ) qt4_add_resources( QRC_FILES qikea.qrc ) add_executable( qikea main.cpp qikea.cpp root.cpp site.cpp topology.cpp ${UIH_FILES} ${CXX_FILES} ${QRC_FILES} ) target_link_libraries( qikea ss_ike ss_idb ss_ith ss_log crypto pthread ${QT_LIBRARIES} ) if( APPLE ) set( MACOSX_BUNDLE_BUNDLE_NAME "Shrew Soft VPN Access Manager" ) set( MACOSX_BUNDLE_GUI_IDENTIFIER "net.shrew.vpn.qikea" ) set( MACOSX_BUNDLE_ICON_FILE "qikea.icns" ) set( MACOSX_BUNDLE_LONG_VERSION_STRING ${RELVER} ) set( MACOSX_BUNDLE_SHORT_VERSION_STRING ${RELVER} ) set_property( TARGET qikea PROPERTY MACOSX_BUNDLE ON ) set_property( TARGET qikea PROPERTY OUTPUT_NAME ${MACOSX_BUNDLE_BUNDLE_NAME} ) add_custom_target( qikea-bundle-resources COMMAND mkdir -p ${CMAKE_CURRENT_SOURCE_DIR}/${MACOSX_BUNDLE_BUNDLE_NAME}.app/Contents/Resources COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/png/${MACOSX_BUNDLE_ICON_FILE} ${CMAKE_CURRENT_SOURCE_DIR}/${MACOSX_BUNDLE_BUNDLE_NAME}.app/Contents/Resources/${MACOSX_BUNDLE_ICON_FILE} ) add_dependencies( qikea ProjectName qikea-bundle-resources ) endif( APPLE ) install( TARGETS qikea RUNTIME DESTINATION bin BUNDLE DESTINATION "/Applications" ) install( FILES qikea.1 DESTINATION ${PATH_MAN}/man1 ) if( APPLE ) # set( # MACOSX_BUNDLE_DEST_DIR # "/Applications/${MACOSX_BUNDLE_BUNDLE_NAME}.app" ) # set( # MACOSX_QTPLUGINS_DEST_DIR # "${MACOSX_BUNDLE_DEST_DIR}/Contents/MacOS/plugins" ) # install( # DIRECTORY "${QT_PLUGINS_DIR}/imageformats" # DESTINATION "${MACOSX_QTPLUGINS_DEST_DIR}" # COMPONENT Runtime ) # set( # MACOSX_QTCONF_DEST_DIR # "${MACOSX_BUNDLE_DEST_DIR}/Contents/Resources" ) # install( # CODE "file( WRITE \"${MACOSX_QTCONF_DEST_DIR}/qt.conf\" \"\" )" # COMPONENT Runtime ) install( CODE "execute_process( COMMAND \"install_name_tool\" -change ${QT_LIBRARY_DIR}/QtCore.framework/Versions/4/QtCore ShrewSoftQtCore.framework/Versions/4/ShrewSoftQtCore \"/Applications/${MACOSX_BUNDLE_BUNDLE_NAME}.app/Contents/MacOS/${MACOSX_BUNDLE_BUNDLE_NAME}\" )" ) install( CODE "execute_process( COMMAND \"install_name_tool\" -change ${QT_LIBRARY_DIR}/QtGui.framework/Versions/4/QtGui ShrewSoftQtGui.framework/Versions/4/ShrewSoftQtGui \"/Applications/${MACOSX_BUNDLE_BUNDLE_NAME}.app/Contents/MacOS/${MACOSX_BUNDLE_BUNDLE_NAME}\" )" ) endif( APPLE ) ike-2.2.1+dfsg/source/qikea/about.ui000066400000000000000000000166561223036517100172640ustar00rootroot00000000000000 qikeaAbout Qt::ApplicationModal 0 0 330 339 0 0 330 16777215 Dialog :/png/ikea.png:/png/ikea.png false 6 0 0 0 :/png/logo_ssoft.png 9 0 9 9 License Qt::Horizontal 40 20 Ver 2.0.0 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copyright (C) 2012</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Shrew Soft Inc.</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">All rights reserved.</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">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.</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">3) Redistributions in any form must be accompanied by information on how to obtain complete source code for the software and any accompanying software that uses the software. The source code must either be included in the distribution or be available for no more than the cost of distribution plus a nominal fee, and must be freely redistributable under reasonable conditions. For an executable file, complete source code means the source code for all modules it contains. It does not include source code for modules or files that typically accompany the major components of the operating system on which the executable file runs.</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC 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.</p></body></html> Qt::Horizontal 40 20 &Ok ike-2.2.1+dfsg/source/qikea/conflict.ui000066400000000000000000000044411223036517100177400ustar00rootroot00000000000000 qikeaConflict 0 0 292 99 Naming Conflict Detected :/png/ikea.png:/png/ikea.png A file with the same name already exists. Please select overwrite or enter a different name to continue. Qt::AlignVCenter true Qt::Horizontal 40 20 &Overwrite Alt+O false false &Continue Alt+C true true ike-2.2.1+dfsg/source/qikea/main.cpp000066400000000000000000000047611223036517100172350ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "qikea.h" QIKEA qikea; int main( int argc, char ** argv ) { Q_INIT_RESOURCE(qikea); QApplication a( argc, argv ); // iniitialize our root window qikeaRoot r; r.show(); // initialize our ikea config // and populate our site list qikea.init( &r ); a.connect( &a, SIGNAL( lastWindowClosed() ), &a, SLOT( quit() ) ); return a.exec(); } ike-2.2.1+dfsg/source/qikea/png/000077500000000000000000000000001223036517100163615ustar00rootroot00000000000000ike-2.2.1+dfsg/source/qikea/png/ikea.png000066400000000000000000000032441223036517100200030ustar00rootroot00000000000000PNG  IHDR szzsRGBbKGD pHYsu0u03rtIME4L$IDATX՗{l[w?{8IӤIy4Mein۴jL*$ҐˆmCh& ҉ڲ6tYݦsHӼ؎c>ɭ'[RM ,9;{~,Z6!hnR@ 8 hps*DAFYﱎm--RmU)E^'N_A-~3j *9xnJ}4*e ϾN<8:emt"\$YKKeHΥv ή-g`hx ,xN~D( fnӴt>ӴQ{dIb&S0L sM<v48dFO˲DV7Ë!朾auWz+n4|G$ {0C= 4-ǀJ0Id1\b޲ n,t.d@0$dYY=x#ai ôF޲ @0U kn,KKu Kd#Ж p{Pg.bpH}EɩY˩MC.X+rpyDQ9OlRyeiq;Cwf ;8 <o7~ߪ:"SU/I2{JwVw> t._+\>͑ooҲog^y\_S{_h.iI*g;N'| ^xW=WuP]Y3,2\QdEysCcܳ(WȂ@:۟ȋzmZ$lG:U 7~n,/pXyJ$T 5-N,?S PQ)Lo@7-Քyo[6a\9U43 X'YR%Xݕ~pv*hL:o\N ?ܹeّ;9s2 9Rcўe灧әCJ?w憍HRᕱm+~hy]JKǶ S3(-bd<9pf}Q߇˩2bYՕkIA^~ (q;Q}Z"9~PV3~qzowR_U@M9|= WՑq. |ԬYNKjW?E¯e,o՗ؿu{KݲVB^HԉYG"S0q?h?JU<&;٫;bj>sD'nij Th޲ڍe]*(02>9ŏ>CDW\}S7t9fU.IKO3zVgktIENDB`ike-2.2.1+dfsg/source/qikea/png/logo_ssoft.png000066400000000000000000000327711223036517100212570ustar00rootroot00000000000000PNG  IHDRJa?WsRGB pHYsu0u03rtIME! IDATx}wWa:wOOYFђ-[0lc&hX%>6ރ},be x8 J#4(Mzs:Jy?,K=5ު~;s%q_!d?l~ټTE6^PО&sUy?{?CqA@ޣ~+E&Y&: NRH:o o-J$k7!& 5T4.*Aȼ`˻+)? `>4 ူ>ثAG_%ηFBOMb$ɽH cJ 41܂D& ' ݸ$B&2' .x!/Nb !%.? BR(c<5}A$Zx7].^0A|3khKߔ%R 0HLitH٬8D_zn@ lb47uZ14x/A%L-ѠNţnE Y*Ѯ. 3j[); A"% 򓟜8qae2re!INNěĠ*jnS7´}{Ҹ9]n% MlC!vyJ7RFxɉlrqljqljMԹs~#"~- C9؛L s!1c`(VV41fjO(YI jL0^ mGJkP|,/ƦǧcSɅ?WVB{NSx(я~T x<_[[×4Mg1l"e22L>cdaNC,b.X.&N[4nP3_REn(dCMBm}ǂ_B3/=ǭ;U5#BdRT* kQl\ƜX`}5je^] S7 ʢu+2$]x4pz!g_/ ,DMfiꖩ.Cr!TegW3[>JS )VjdCi9i,yl`tnac=O[-~~x+j,tOݨ(Tx/_jrrMO2z2˲DP9oi$ERoA(YZ!*邐P0,P$BDD, 1L(JGuenk:h8C/=v˔yg0NӴTYǦR)G=~d/ IRN |ixjLNGN v5^@G+VPhhz@ko$jΏb?qN)z?0qy$IpHe9Ki PNlJ ŀh@>z$k׮H&A)6 XQY~uu4[L( юY( YWΌI>ٔlڊЗnwp8JְtMRd2ODH$DEtQ60.j[y%VaVb~#;E|v8;@q G_`K< f R?$3ꫪFPAu]f?ӧOwϝ8q>.~VQa}oT/=wx?0+(j޽{ /s=h4t:--swd(gҗ'\C>pɉܼٳm-Sz:I{/H<ԯC/ٳ@659gvyr7:M©ƾͿ=Ff{x_^P,?H^Xta~{3B蕣/׊6-UDVZ4Sۛ:bi5AQof,/wbyo;v[z)ۇ+~jvq?f9]n:Bh-(("B> 7bZ9yyʇw&7UsZ`]l݂PSse 棟|o߮ܝH$<35FO<{NrE A/i厱 W˟7偙醆#GfJd2LR0h z{{{{{?{ CCjjji e)۷gϾkWs7pq`0|rX|d65VW὎ "Ǚco#@`ʪm}xicӛΎ︫勹ׄ/MyMsBA0 B,N>I/SMaBKx49}/~|I----qqTy睕E)an;tC_|^xqfvG:ٳp/t;tk^zє|;7B(ž9Ae Z _!̛mic~v^'c*Q0qSU ,_Mx#x^`1 1L=wt:^xWUMѺtRQn}w}]z_||U T _@!]J" .= r17;=:r#\l}CӅg}+RNSP&eu㙻K&@IzR.弳"IS^<ٻǿi2[%QIVr8@m۶l6^酅ŅEt8l6NGrd2ɲ˦9B{{^/gx=4MJi4?lߍ> 1E|2g(1Zv$IQ.g9>8{{[T`A\+U@  endR6 uU}G1 xK'X]i]=zdͺb .ZG$qE@ /$| c(ٕ۷o߾}W.ͳDzA߽{h`طo#/ϵo|w>p_p@b{ugZ]{өTA/|H@sMKE()X,ΜCP,M$|6 c ܳ~܏dG9q巿u|uwÍRh eQƒ]$7ʯ$p eq2Z>y~|jX'RӋ# WFfFɀ/BXHS=]=B VD|l|VWW[Gc 5GH$2703=KPTmm]F:]z:3pӟgL 0]{Y,u2D\nO:_3olji|-ʇz;^ws3y;&'F/?9xkPn/)%Q&W1K@P[{xoNu}KB _WguaYa6vttL& K ~PW[S__k1Kfy=5r+_Dp,׿W};Jx<~ı zp:]BP`e3'oJN djR['>|;/ $yۋv^UR艍4N\w !4>4=h PEm}ߝEDbdtgwAUU~;ޥ_gY}e (B=ޗ1J=oyIXѐ2Ʒ9{[4rydfRO}zdS*Sz^o(cQ|( R2wẅ<cИj~r_4ۗ;nbk46M+K( o~qছҒ [n~? Qar~繛F}h4fOADs}chb6WTWtv`s raox;]nߵ74ӿE!׿GN~sgO,y˾JPhU:u PP uCNi{0:ɦT B3&E:++~1"$OY(b;uÍʲFVt"g3St:Q;쾡홟lkA*7("rͤSPccdždR׻dLʪّ6#)ڻ@"8u2U:3't;wBJ= ǏDM OpCKKDu6u}&E33ΜE#$E֎z!SdhT2 RajO,zzwQhozkw@"is<~O|_fNXoGS?dur^M9cۙ굱ƦŌF/;fOi(: ̗!DURV_4sk,LҚcLF9f4$39T*eX̕[1*4JkDhB3>Wv <c!T_r6B(9)30p\9׃|pO;P (lGhA9eS錾D~G*1+wSHQSMͥ˄wL^7E(Ninkd"ւZCq_>z[:I^99JB]]s "L?IZjl,xXxpq4r=cVĦ)`(X,!mPUKe #c'>?Z e? ^ŁߍJ%O{AQl\'< ;;`zH\D4 iHi&I0L_Os{⶛vwwg|u!+v[_fIH>sBAU>g_jdl_y$HOԁWTq_ 85z)6wArH,GZY>+|+i@m17~ߨjxV5ۙ܉hpuȱwn2I`U:Kᐩ/|D217Ȱ*l~b,薹u -7Iucilh|}_yx?T`9)qtWJw(M`D]%~ǧ;ɲrdj&Dpqo8?nNX^p N"XYD*Uqyr^zhvt4s[kju<۫9Q6hFne9D#k^~e_4{k둢sW77"'<N̙Lr+ ^׮8eJ$c4﹕esm)S-=  wkQ"Av_*@Z7ٮAktv1Fg4$sKCjSChzP\9)T8_#B2ӳV}gG.%U5M=IDAT r.Lqs:٠*/! ÝfPF}^x>0 c6Vn Yl<.3'n4ҳȇ !.,qI)^=4EDDIHa?jpbjJYAs6&l2Ѣj ._M+rMPƛnni,v•]ΚͩmW,$I6755V]8(znG`06pvj6teH1x [[;HSv:*D ڬx0!#aq9JEPXTҎ X=Jb{rL+,[]M uyAf BYEr†l7i3W{m:0bPlh4 2t㸲d!E f'N[V/9"[ xK޾J' x7"_c9ͲG/Wd0 o5cn^Fx#F_{3x `0把 {Z&aL2dB$O:V_ߠ,lPsmoܘ-񹵵f)n +Qds K//)EAdT E3 qV)B08E.oX__0ݳZ-E%w-VΝj:_ bE0L#xDϘ}٠Ɩ6? o *++MKZgr3g:Z[E6kG!.P(&j{2I;J0wZodCYUfF[ 2D𥅅EcXaM?y,Ȓ?<|oG}C^9APa= ců0ķEi~ wQh3&E /2 B rL̎,ljvҗj7LLL-ܹwE 7s׷w- Gbb~5iz[wjq.m!C0[xaUL-o^_QQX, ^6DrI:XQǵ@[8D"sg(J\bPZ]_Ua*]Z !ۺ[qhD"gPF.knN-^DyU1,?X6J3x*H%Yhu55EM1gB9rX,jTjD" .vvvn(uKyRr>.qsjb㈁mO +-Éctu%pnE"7EJi 3f wUֶF>X]k+sXTAșj킧o!xgkz3^r#d%cvOLhZ3@rVH\T6FXuzcn(.-eSUu.~d"~íw{kg,)U3K=ZA Z$; --EbVl;9rmǓצ } mCN7ja@|d"8X](˦u cX.wS!nx4 ҨT̶T*GX" 3\u ǐ: D<,< ﶌZ cŇ7"YIǘ)Z/:@ 3V7B(HLNL9sfqb26 ];ٹՕ/EQ@qX49xB$ɼFu2O$h!/ $W:;DoEAbǐP"f oQAohnn6gϞVKO.W!w۝""([3H[6 gɊ 2>VWy?IqU%JJ;Zp#࿲H E DVw4]]Sc00&iҥD"^S쁌=4tttuu[֬jVJ[gmWOi,(OjW"I,bM&ݮe boъRݒیNn{׮&ܹXXCa-t6Ʉ"ef,d* ԭ.y:MbTDjvU!yva ?z6 '-Yf Z7pΝ0h4688i6u#9 @iq2×ܐ'_V3HZr,@ag>dU{qZ ̖7G@&sp$A˗n5{nTZ( H|M]5)NLV ё]@b+xJX)[޾Qr 濰`hljbٳgz|>_&|a~~eue׮]^o%EJ3[UA ,#o Χ: vPe $k#ROyK*v)rn-xinf MUzh2]F"7􎎎r{nELuI au˨WLQW)]UU-8A%6@ACx,@QJEok{gr`C߀%fʸ"]Dd'-)kTe)GQy{XeRzX:<#X]M'O#ފؖ^ lV۶mv˲uuG 2GGse6>9F TVۓQĩ[Cߞj&o%uv}v˜M PMUą-4ۄaH ɥUgȗIU.zȦR}Um/|R2DTJqa8Qc[fD3) b3BI\Z'pL><0*pF( JAc`@SŭHںH1ϭ쀡[-DZn \nR)1I Cuㅲ$m!<~m[}0CYlBN^+[( He{k~)*)NFVgzeKө&pIRPLȚPc8Tp: ?ᇲd= a{Ug7~0*Ut1Ez rmCX,Pd( um {@PKr5YA֩1]2 `؄)!j~R7]Ғk6xeAjsPfh*MPK %%Bi񆭝IENDB`ike-2.2.1+dfsg/source/qikea/png/policy_exc.png000066400000000000000000000003031223036517100212210ustar00rootroot00000000000000PNG  IHDRabKGD pHYs  tIME_[PIDATxc`@OO?&"'D)5!,h.]B7h ,HlF"HI0R0FsR"IENDB`ike-2.2.1+dfsg/source/qikea/png/policy_inc.png000066400000000000000000000002551223036517100212210ustar00rootroot00000000000000PNG  IHDRabKGD pHYs  tIMEV:IDATxc`RHЌU 1202Q`8HÀL)Q{ }IENDB`ike-2.2.1+dfsg/source/qikea/png/qikea.icns000066400000000000000000001620371223036517100203420ustar00rootroot00000000000000icnsit32$x!!!!JXsƝXX!!Uˏپb.!!9vE!!8qĉC!!Lb!!I]!!=P!!*p2!!9R!!Vm!!h}(!!b͡v'!!]𲓂o'!!Xzzi&!!Ds’sT!!.ktkLyWbҰޚҐLI!!#GGRGiuхuG*!!+BYBYMB|qۄĐB1!!/>>‹>bVJ>6!!19RFE996!!05B5tg5B5!!-2e22rX̐2!!+/}/˂/}/!!),a,n,ʽa,+!!&*_*_*7*'!!$(](](((%!!"&\&\&&&#!!$[$[$$$!!"#Z#Z###"!!"Y"Y"""!!Y/Y!!!!YYY!!!!YYY!!!!YYY!!!!YYY!!!!YYY!!!!YYY!!!!YYY!!!!YYY!!!!YYY!!!!YYY!!!!YYY!Y!!YYY!/YYfYK!Y!!YY㺂Y!!YYȄ!!YY!!!!/!!/f!!Ktft!!tK!=/!!t/!//!!t=!!f/!!K!ՙ!!/t!!/!!t!tY!!"Y"0"u"!!"Ȁ"uL"u"!!#hL##?#1#"!!$$?$[$"!!%\%%@Ʌ%N%"!!']''֌'"!!((^(ɖ(#!!***RE*_*#!!),n,,,a,!!+.b...b.-!!)0q00ː0d0,!!'333̐L3f3+!!#555͐h5͖5'!!59w9999"!!0<Hy<…<T<7!!'@@oK@{@.!!?DrODD%!!4HHƐSHH>!!$LWLL+!!>PӀ{PJ!!'TjT1!!=ZdZL!!%[_i_,!!6ddF!!Risi[%!!&eoxoj/!!1pu~ԥu@!!B|֌|T!!Eࡎ]!!GӦa!!J亖e!!LҸj!!@÷W!!1A!!o*!!Ea!!n+!!5J!!6L!!7{̒7!!\՝h-!!_Ėўk-!!.U͌b;!!/XX99jő񧒉y>99Xɒf99E{߄{Q99ju~~uq=99Mooɖґo[99cisiǘi?99IdddQ99S_is׸א_\99;[[e[yօ[A99BVlVlaV߄ʐVH99ERRɋRrg]RL99HOdZYOOL99GKVKxKVK99DHvHHjѐH99BEEтEE99@CrC~CrCB99=ApApALA?99;?o?o???=99:=m=m===:99;<m<m<<<99:k:k:::99:k:k:::99kEk9999kkk9999kkk9999kkk9999kkk9999kkk9999kkk9999kkk9999kkk9999kkk9999kkk9999kkk9k99kkk9Ekkwk^9k99kkk99kk΄99kk9999E99Ew99^浃w99^9RE99E9EE99R99wE99^9ڙ99E99E999k99:k:F::99:΀:_::99;x_;;S;G;99<<T<m<:99<m<n>>ی>:99??o?ϖ?;99AAAdYApA:99@C~CCCrC99BEsEEEsED99@GGGѐGuGC99>IIIѐ_IvIB99;KKKҐxKҖK?99LNNNNN:99FQ\QɅQgQL99>TT^TTE99TXbXX=99J[[̐e[[R99;_h__B99Sc؀띉ėc]99?gzƮƋgG99Rlul_99 jP ftypjp2 jp2 Ojp2hihdrcolr"cdefjp2cOQ2R \ PXX`XX`XX`XXXPPXdKakadu-v5.2.1 =,]Ƚ W')T2}Qe]d7jd?_0mZwߨ|:]k])< h8!ٖ?]l?7Yܼ]}"vMimգ4V٪bSP"Rs @:i ~bLpEZ,HE7:d-:#`t:sX,PTnY4QU19JBV @FO %D܏?t,)Fz*0r^?à!$]utaC[{gEgv@@|@E `=nei2*Ḋo2,{#_n9Vl7cC? F$LƹͶ4*qLW %fܘf.2(CWS|&2  '{oasx=>nt$Bf"6mb86. ,?5>@wGp+abUZ{M؈n8i')~?as72yk.+7ttUN $+ qa=ϗ /PyБC4DԷoځInr1:6cU7%Jz7Çq&<@/۸Y#Yhhd6 Zg P`^N;k=ZMF(aK$*$,Fx.<,T'BHO=;o2;_j~iklSߓR}R` @B9%?f{,;4A@q]c%3(ӼೲLcb1˺1?zi$ qs|H`͢d>WP=Yyf 1VZi 8R]4;AP-*Ч K%&~H382`l&ߙO@|@-C NԳKeH,YC䓥7Vx&:g\{#wi}]MG;mu)S~ׅtgjʐKY ~g{*ϡ2Uw+#8 "è`<>(s%D^РY)/\:ژ=J>Ϋ$GІ6YR#-Ion:z wO,gH5J[?#@&f 4΄'v^c7(nApz7#=?Nl*g_MsevsGc 0WAt}^P)[3 @yZi7#*yÙ+?2sV8`}dRH=*ܪI/j5W$q8L§VɄ~g_̓+J_<Î.T nx #Ru~`8lZgybsϢ_O! _FwJH2TO*5$ȃ)Е L)åiz޷eh?*G#!)L Yr0- BX o(IHAiB6K6b4y^B^{xrzpdX_#_ge||ȨB1!${YV큢oì$466N:ѺA~ErS*jf}xqs6=R"B Y@22jO&cC̉(a:T8u.A.^fQ ʼnǃldD5:ī} g_h*473ѨpPՈNsdTRdsǢct]#'9D?IQџRuB;'E[6LLnz8ozvB Ɋ܌HhkLn1C^b?1R}T|m4ƧȈ zz¯nÕR1T- j{1@2Om= 6z4!4Xektx%ʒi{/rf0&O#oK:bPuX''NZ{bet ѣ \ +iqяfm{i0{ ,ߵy\A>02Vry伀1*Kʼnd?]Mk %! ;ge-s|o9&)35=hѓLyuaVYW.P9zW V'ڥ fR 7;yNaܸzLaܒq ~ģnk S4^4p&^!}7CAbӚGkΞ:?'(Pj2) cTB[0*Ϋ"R>{Ƥ*LŴL"w1\7*Y$ - g;yH6PQr-ESS"1zޖMfƴN X:h~ |@+ʄ(_۟SVջxu:ЇZ'\nMZGHiNĬf?ac-aȭL 9H_ !v:hjsV C'8}0! I?/^7.P9zW V(P3XrU3s~d$V蔹?AEaCw햜9p^Q>^GN2[ ֣1o_'0@k_TȕK*"ؘbZe ;{1<<}O}RLۋha&lqiHXh̭/~.l0Dia'EB->S}蟂׀1c܌NI(x>\(l)g4Ud/(wD ]?עrW c1bקg{~Zn!&lxާ[%ߐ«%'xL 7e^l`/F!$_b9}񬟬]#فZ&;<.otUW}MԚIc癊)tvбғz}"аbpLŝN?"-}l.5KVvdSYYx=Jњ7*l"'vuEUx[jg_ƒZhn}w@vMй7 =HMe\dyWtBqjT- EIkzʶL>=`*Yr#A: Uuؐqq^ҡ4 я)vJ  j%I} vkpsP3,уH]&T=7M,:gZT`/Ӆe/XNl7䮣l4n^fiH0 YkDVj0k3qɿq~?VHNhjBmE&5WDr.R.E+d2د@.t K&,EjM󔠂)P٣ a=nQtۤXo 1Qˏ1܅%>VFʶiq>bֵF9<}tF'&VT%v}zwuKv}Z ZvbyĖ]M@ywE@̹JaMEro(G,RB )M cPHe' Vǥ'h{ ԑX`ߣsD6lpd]垤oiŰe~l3n<FCۋ8=Hk;Y!N8[_Iq+:GaAS(4=at1D "2\\Z=zL6.Cˋ8k_P?A37i}=kbYr;=FQ6R&}uVlSPE>S! ~zxo߸cj?w /\iEPF<%*юﳪuǓgUr_ͮ`p,y&P̯XB~kଷwVf0bm*nmlr DJUXetgUc`W/7϶FڸSRk=f\s,qe{[J@[r;jxpTJK*ǎP&@]PyIxIUQ} ܗtPR;XʔE [f~JM2DWQ.*%1;p92âьZ>?_*Iqc3hR4zr1S3,~]Gq?ȆܨF A˩1lU![W}R&y)_XU:ь?$fڜb>NR(;-bGT<:l'&s s7s7Xߖo E$k0fŐWG,5/ ڍy9AE% ePhm`4wR9'8зmdC401൲dx(=<|ÐϣGBVH4ߩE9ˉ`'AB*qWl[{i}@MB8KV&k9y?gm?hcjDL&AΐkPyĦJ !d4j~pC2+jLa*0lL QŒaNYnwyϞߟ5/ 2U*\}ukl"#DTKi(NQu{ ס䮑7%3Дi 3 qSÚoȃ{WMn$Hxq"gRV_x{>_;!٠"0Z^2{3Es9b(bUL_ i&_~_ l"1l0&ҮpȻ;tuNgaI"uմ׫0EE9W}gOϘE?x9e!iV Մq>!dj/@{Cj%fD,xf 3ӚsLR>6n/|xy]R%n_,NQk]$)̔R4.?Ư*E?LWs.R3qdyytbӡyYҷp ET:|"kd "փ/&U2WӆG`EXꋒ>?B:`Ѥw=]>FMy1}!}Z#E۩a6) `^ m2o?Fm@q$ ɮjf6OG$eV'_ed^1 :U{n뀓u)a(LLOkԉsWO܅n#&Zč;0'*{!(ڼ5ɂH4 L3CJxm맖ہBUvVjc);zHa3XkiԧI3'zTzڅf+LU'd8:?b`-"&#~khF?;s–,Թ.Q޵*7 EQ 8{oѳrКIz^|a$95_Ab(Q -\ ާrbh]Qx_}B/CO?bl/X_m>}}oeE+ay.BV!<;[c֍Γ[9#|- ~~ ҾA/6"W796M_7PԠoMfלwJnPG3!@19V\rQzZ8S}kU 0)s a{!G{l oɕ%)‡}Q:q=g?΄}gЇ E{mLb莯~(RޝY~7'K].f-`ř^3knG8_ϛ9 rv$4Lit[ |~"'T\dEnO]+ &Γ(rބK5O&pک-~ Em(:h%dGnUP:Xη뽲O佰!8"#Ci@0}8EqHN'"鲞:1(y?rre{q ha&$ 6 1Hyb[ ݑy)gedMH3mnYģhW"d~*7O)vQ4us94-tpO$=O,; w0w<+Fu`'XVɔ1=X6нT4 l9 r@3"PSc$o%YQKV: 즐cMy:c`jHaFXK5P n=8+Y.AeĥDN>{eXDW޽a![ޥ8ӗS A5F:enygU%p%Zr ט9Q&z#*m92NkCx|AE1D_H1MuCJ .R(Dֶo?82xˌ--8Q<2D_߸*-)IM0`5HgO03R>q\LÃRIkp0kewT~y2hU Wo^\bF"'ƍѺ,ȢKa ;_y܃(dE[$ 'sבeD*52+LYiv,QYÝ S*kse/{ Gw7`1w9+G p{[HQi@N "_N7[K[_Vudn(_?|BOG$iZ\M!T|^_zS![,M{־T;OJx,3Zi,"l|³:.mcߦF4G֗ q7C0s22لO+5 3+ k|e1Ua\Gj({ce~=Dg ىf3Ϡ˪P=PD(٫0Pk>aS'ВAI ![4T>u>R"0HtD @( G;ԍf3kGT)@udq~.{`#u=qw> g>~TDwoO&lLYw@wZ6T Jcc-yB98Q'rqK )JVjdI>M8 `e v剆} @ %=+³u>k0 pDT{|B2nFT4d}66{Y1&F!{+01R">,RþyeV#3:]<T6bcQaߛw7v =le!_w8)ChǠ"Tw=r؃"?cn)qKAYk(tt\#"|HqԀdgeaE ,]t'Z!i.#ӪYG; ܢ3r NӥU24"Q~jgK呖R?u ώ؀dmA^Dmt"8MVN2 .W~uҿT~kEYNg;rIoU~Ux~VߪUKCXߪc$RR5C=}Uu{v~07ӀGU2.t`c#m`DVqP\B.ZzH¤i/g&qO^Q Hᨎs?OFBgl K}x_#T fF:DqGWYjJ] n(V1Q`kT..ѿ?S)U0`;H_xi ALnbzq~`f1N>ti%<ȡKZŠ8r,Yƫ /HW$9R<Nu&lo^^0a|sm(ITPTqn풔tQԈJCU{nqF1Զy LryVV9SCK5jEȩ͉8Dj )5[H,Cg E!/yt3Ƅ5+9ZS82'Dv^M_j>/wѢH~=>Q4m\{ʣ] LRuƠ;LuEiՆ5tbimD:0:THF܄ueb6${e D#:tApD f.KY氡Y^:-]9ʑА[Z1Sf:ǡ .C>R}[ؖ/ b[/H.MCMI]J(\՘}qRm(v~v&*CԋoS""Vh7؎XءXc2}AfPQ;dɽLAD|'QuoN] _K^;$\yXBT^(oR+E~a|8f;h;LTE*1eO +fIJwM8 4 tΒTLTalo}OqhS4Y9д#\qϦ]ؤwyo&]9)QS3+f hkEqٗHrᅄ[PW~HnD.N5ԡe]YUQ1z\FN0V_ `8ARR}?m =,$uC )g?UEl"4S\2yal6K"Sf 鱭0k:y Hc-6C aYM#ʊ?wB/1׳OV 1.GNts9`p)EVuxLF ik^/Më9!#m53AtbgNΐagh=b:+?kk4yzv닦NSAeGϭ?>_\~}9￞ c$RR5C=}Uu?XJ];iZyBGDO)8;0^?RjW;8>M~(T/;݋S|o8&KUvT[fF '(+&_+DAu _y5RqGWYjJ] >:eecD1B{{%TFF>pZ*-3hbaj b=gjފ zc3c*(ǣd)4͒uEe7qL7j^zgFRKYٽ/kjsPHpĒQ(s\;$ pQW&qeQOU#fMbM&p`!FCh `/a3»?\i/($|rLq& Ȓ5`ͥo1(aSǴ>6Hm꓄ &ym1@>}1ױ.aE~JcK[1L18_;t,j/I\dsi> ` 4OL d('_`9PT֭]lI|U1JΝ;eڒȍ~X|KǁŃ~@c ?Hܟ8f5ÁUC؍J@m*g 2 Dt5o8CE^5 yv SUqHVel8p^rWSxzvDfNsӲ<Ƀ0xg>"s"P0w L+K8,ȹLW@Cv,g,t2 ZNJa4'1~[EEfjňx*n<fO +`˱YiÅ{$vcqglKGeX?tv]pQ[j128<#Kv%u#Th/˖)& EfD.N57 8yvR&b!1uTƝIVq-* p9銒[Q0㳭@/ ڲ*}LmQv5W|78|_JA⹲(M2 vC%1̑'dgd>̭$?-U8r4#}j$> I=Iэs-#5`id>SK }՗a|2(њ6zˮ1g%T/Zb䌹L{\j%/^e+r,w#NzzQܚ>2sgrHd9`h9 E)L~w4{~ROᘥЎKAa)0h5 I:+$#vv)F2gtmcHK-qP)˾ծٶ7so1}9DǑfEvC>f9 Xш="BOjHmEAw=랬.LiIqX҈s;ʎB5:Y/mj%1As gB^Hxw vU=K4PNAEѰ"iyhɯAG49UR.ߜecƩ[h.O$ ?~p耫Fb_nvqZ@dKc=4ongή&Vc>ݧ.mJ/s)g~:G؜v#L A%\6G. +s'v}ѵJFЖ /ۍh g#7֭:h(7]Qi|b8}܄ x25x]q7niviEx/l} NOFH2ic09@ jP ftypjp2 jp2 Ojp2hihdrcolr"cdefjp2cOQ2R \ PXX`XX`XX`XXXPPXdKakadu-v5.2.1 @l 6~c`e'yd ečHK#?lkH0k+p9A301ZAJ]领2X;FL?G{4Er7,!+hu'|QOdғe`zR癇}I[{/~pqPT]R ?4cJ`"TX*3m| Tn=yH)DFn=2LzuWֆ^ _|?zȴ) f0DZ&N SyXI{-:Tz5lxȭ)ԡ_IlMDS%^QYD[Y}V;m_,യYt􍵇 @3F#?8K:}$wgS?!c.Vb!0I\'k@@|倒2ƽkZzAOvU3_xyg~wIG?@ܹb ~޲ UUͳ^*;&6MK6FjK3NxŔm5ٓ/AB\ނ ;~gQX#\"88fA9?5>`<_3da JΖB5@4Q/ܿf^^{z0XþOmxyNvБO)>@Էoځ bo8pjS*:2*f3lmM|5_4Ի7q'^HKQZA˔=KC 9ZQímgU'uY!V$b7Th<}ɠt41l4wX9'UK?K|Cԕk*{jO1 6 ilpNXv*i;6 nvh~ Ts|Fd8b'o |Y_˺;5J3 br=;{bF=VԵEQQb^h4*$ h4eMƐq"o$i !CMXq¥$+yNU¡PUP:x"=@|@]"ZѩfybfTMˏHG90lHwvYil4Ԍ*F vK.]2)kw^pQ4> `] ]L Á~s"򏕳|n}&NL8@0!F瀒5+|;oJ5Plex'' soGIAs,wvFdEF]ɨ$Q Y0sfs^pBUrhnz8ozvAe1AUrPT=AqW2CuPqr=F lSP}Tm:d2NozK3d`,ZsaҴCTt}#ᙍ.w9[`<o#x>ۍen8Mԋ^ʝٺj@4,͊Hӓ\cPU4uzHOhх_ \zNg#kwEWf\:$np$]g)00̛Bʝ*-`ZXFC.ᦂh%& `|V2I>7ˌMɖ4C"eJZSѓLyuaVZN"}Ւrcwx~M;nk3e4*iĞ6cbI*r %ⷐ{8IUzjF6ւ$M}`E=jY"^с@7<#5 cg߲فUVuXu>{Φ! n&Kѓ?uMjcDe+q\NP{3dWkxKk7KI2Y`o`[XgycZFžpb#f)# pmϋ)kĉ vJ^̀j&4z^ Ƅ}WER_ L(⒁AcӊBe.,2wy>gPUKV1CWlz>=Pnhh67o%fk tmåD!"}Ւrcwx~U" Id8\BrOBTdi '^~>@ņ?6Spl Ыiͅv 7 ȕzڄ"[oE]x8}J=N{AG@C%smi{yBlk6I$%İ;SF Y mH̳Ѝm}l=@" 7[U]lk銥1K-,Ou 9&Y^hEȁMvV,5;D y!a8@?Iث~ Y?APdddp]+iy,ϼ.D^{pJlDzCN->T+,$xp][91x5n鳈u}#¶bqrؤdP(m{"hM44!kW {PdbR<O5yP¨ߦ/]&cmGq]=S4R/8@Vػi4C2,@Q0rHU` _X0ʧL$̃Ȗ$32giDR-21ȕ+JnXQ0wse6YyƩ&jQn}ͯqeUYن@' +gg4)]tD%PRl I #V@ r⃻B~D9+'.2 z>_[, :"n MZx] z^W= Vnm%_ GݽM22< k z-3NC"6LjTj׵R^^+Q9oKαARO)u Zx`Gmm`H!d.C %7ٟ_^ ҭ̗Kn=$"G$csUTufƌLl|Yj㷏v+Ư|-w*Sp_Q"3@#$l6E /~"x'`G`dE,Y߯# --ɴR{;\nN 9M#:*hcZA3R/gf؍ʏLryg"֪m>ior[F`|he MF)A. Ѽz w`:CX^.j)DՒm|atNw]_8*$rodɑᰵX_ՙ,-A5L2ta'Tz#w]U>7TdRY>EF.ytyT$+ޖvt K+0}?]38ʎ`Ie_r`omrև-Ѵ^6cTm?#x-$U S\}*eA(XAY%rM(-KWM]?RhL?RNM_dAd4)4mhYNr;V ihخO KHx[L7Ý!@ޟoѶVOQΌ+k3 !Ȟ'_DGPr'N v7 +]B{zLe0m E3Նl<́ҲLln=H%9FwI$VH&(_dMG}ûTZ'jMآ9()FO |cYxdëò^>_*Μ]S 4dD{rT]z:O#sIҏ|ݮ/TZI8N ^r÷"?V0\H3+ů7J*"fv1ytN. wQ'mO۬W-"=@bqoW#?8O但).[U:-󣘨Nj2&} }n"qqscg/5/! ''bC'ImW:T֛0VVۏaiMDȘ`Wx=@Om+,$+y'8v q>=iq= V&i˞_TDWsHTnKf\LcQi?v~z_~zQ?=+=_0?=I@S|7h]Q-52%:ώhXا!TtZh?04U䯰T=bQ=<M- íƥ{e- ,YoS8Fe;[KP^><>[Q5t-Ѧ,59qgeS L#*̀P<̨Ü{k'S/" ZKt"c&$:.ʍsCA ҈.>y`ug4 ls+?~}_/ "Nj$ܿK,{.bRXd\ ߨt&1mF"{RBSb0ҨWlƙ64%%ZUќWWQnx._4+9q]Ht=eȝ^)`33RD+vJ\\47s30_gސQ@[RŧVFJSkvrȹHK T<"wH> ga wxYT :MS㋮ꙃ$+pHC̾S)w깣֚H Vb2eDj#Z_z D{P+*wVn&sڒ)fcVªe rQڛE iMBi%BAŵ }zއ8͗IuGzeJ]|*\s:±?mc .6-xd^%qAPE_mG1|ւU$J7Ta=&-8s l,N/r_t $ +"+y'8v q>=iq= V:7amךrBRd۠mQ_kp&zԇZ]F`#?`N?7>?@˾8xE7,g1y`dg2e56(٫99->/ARG]6F߅=yDCa, |Ƚ ۢH6?aPٚN%q_py6,=RvG\/ڶI5'8DȧuHd1V@3 n9{h5=?">kM+h˜V|7܍M +jt K|&\zeϋFGƪHtO7 fG*V?䮺kƅL#??0ޅ) W{nw%wĤМ@[nr/N9+CV egǃ/US`u5OCG|ۑOԖ"^0 Pcm>ԱH0 JQ nZ݊pQO ! Dц`(ǫ,#G0IG]3Sta"3XeDv=/* KV1?(_h0"k\$&H߿!*ىC$G# //ZVaR3b_iSHXH8~ &Q<&[t-yy>&䳝I]^bFKɌozۑ O3:^X&JmLu̓~) %Α!J%7MnV> ny`OӁG &_v#v,|\],iߍQkk)*e=6_Oa~/_ȟwB_᧟@dEl/ok}}oeE+ay.BV!<;[c֍Γ[9#|- ~~ ҾA/6"W796M_7PԠoMfלwJnPG3!@19V\rQzZ8S}kU 0)s a{!G{l oɕ%)‡}Q:q=g?΄}gЇ E{mLb莯~(RޝY~7'K].f-`ř^3knG8_ϛ9 rv$4Lit[ |~"'T\dEnO]+ &Γ(rބK5O&pک-~ Em(:h%dGnUP:Xη뽲O佰!8"#Ci@0}8EqHN'"鲞:1(y?rre{q ha&$ 6 1Hyb[ ݑy)gedMH3mnYģhW"d~*7O)vQ4us94-tpO$=O,; w0w<+Fu`'XVɔ1=X6нT4 l9 r@3"PSc$o%YQKV: 즐cMy:c`jHaFXK5P n=8+Y.AeĥDN>{eXDW޽a![ޥ8ӗS A5F:enygU%p%Zr ט9Q&z#*m92NkCx|AE1D_H1MuCJ .R(Dֶo?82xˌ--8Q<2D_߸*-)IM0`5HgO03R>q\LÃRIkp0kewT~y2hU Wo^\bF"'ƍѺ,ȢKa ;_y܃(dE[$ 'sבeD*52+LYiv,QYÝ S*kse/{ Gw7`1w9+G p{[HQi@N "_N7[K[_Vudn(_?|BOG$iZ\M!T|^_zS![,M{־T;OJx,3Zi,"l|³:.mcߦF4G֗ q7C0s22لO+5 3+ k|e1Ua\Gj({ce~=Dg ىf3Ϡ˪P=PD(٫0Pk>aS'ВAI ![4T>u>R"0HtD @( G;ԍf3kGT)@udq~.{`#u=qw> g>~TDwoO&lLYw@wZ6T Jcc-yB98Q'rqK )JVjdI>M8 `e v剆} @ %=+³u>k0 pDT{|B2nFT4d}66{Y1&F!{+01R">,RþyeV#3:]<T6bcQaߛw7v =le!_w8)ChǠ"Tw=r؃"?cn)qKAYk(tt\#"|HqԀdgeaE ,]t'Z!i.#ӪYG; ܢ3r NӥU24"Q~jgK呖R?u ώ؀dmA^Dmt"8MVN2 .W~uҿT~kEYNg;rICoꪗ\_?_uU]"UH/걿Jc$RR5C=}Uu{v~07ӀGU2.t`c#m`DVqP\B.ZzH¤i/g&qO^Q Hᨎs?OFBgl K}x_#T fF:DqGWYjJ] n(V1Q`kT..ѿ?S)U0`;H_xi ALnbzq~`f1N>ti%<ȡKZŠ8r,Yƫ /HW$9R<Nu&lo^^0a|sm(ITPTqn풔tQԈJCU{nqF1Զy LryVV9SCK5jEȩ͉8Dj )5[H,Cg E!/yt3Ƅ5+9ZS82'Dv^M_j>/wѢH~=>Q4m\{ʣ] LRuƠ;LuEiՆ5tbimD:0:THF܄ueb6${e D#:tApD f.KY氡Y^:-]9ʑА[Z1Sf:ǡ .C>R}[ؖ/ b[/H.MCMI]J(\՘}qRm(v~v&*CԋoS""Vh7؎XءXc2}AfPQ;dɽLAD|'QuoN] _K^;$\yXBT^(oR+E~a|8f;h;LTE*1eO +fIJwM8 4 tΒTLTalo}OqhS4Y9д#\qϦ]ؤwyo&]9)QS3+f hkEqٗHrᅄ[PW~HnD.N5ԡe]YUQ1z\FN0V_ `8ARR}?m =,$uC )g?UEl"4S\2yal6K"Sf 鱭0k:y Hc-6C aYM#ʊ?wB/1׳OV 1.GNts9`p)EVuxLF ik^/Më9!#m53AtbgNΐagh=b:+?kk4yzv닦NSAeAG}i} ?Q>_Ϯ?ϧ|_ϨϠ@c$RR5C=}Uu?XJ];iZyBGDO)8;0^?RjW;8>M~(T/;݋S|o8&KUvT[fF '(+&_+DAu _y5RqGWYjJ] >:eecD1B{{%TFF>pZ*-3hbaj b=gjފ zc3c*(ǣd)4͒uEe7qL7j^zgFRKYٽ/kjsPHpĒQ(s\;$ pQW&qeQOU#fMbM&p`!FCh `/a3»?\i/($|rLq& Ȓ5`ͥo1(aSǴ>6Hm꓄ &ym1@>}1ױ.aE~JcK[1L18_;t,j/I\dsi> ` 4OL d('_`9PT֭]lI|U1JΝ;eڒȍ~X|KǁŃ~@c ?Hܟ8f5ÁUC؍J@m*g 2 Dt5o8CE^5 yv SUqHVel8p^rWSxzvDfNsӲ<Ƀ0xg>"s"P0w L+K8,ȹLW@Cv,g,t2 ZNJa4'1~[EEfjňx*n<fO +`˱YiÅ{$vcqglKGeX?tv]pQ[j128<#Kv%u#Th/˖)& EfD.N57 8yvR&b!1uTƝIVq-* p9銒[Q0㳭@/ ڲ*}LmQv5W|78|_JA⹲(M2 vC%1̑'dgd>̭$?-U8r4#}j$> I=Iэs-#5`id>SK }՗a|2(њ6zˮ1g%T/Zb䌹L{\j%/^e+r,w#NzzQܚ>2sgrHd9`h9 E)L~w4{~ROᘥЎKAa)0h5 I:+$#vv)F2gtmcHK-qP)˾ծٶ7so1}9DǑfEvC>f9 Xш="BOjHmEAw=랬.LiIqX҈s;ʎB5:Y/mj%1As gB^Hxw vU=K4PNAEѰ"iyhɯAG49UR.ߜecƩ[h.O$ ?~p耫Fb_nvqZ@dKc=4ongή&Vc>ݧ.mJ/s)g~:G؜v#L A%\6G. +s'v}ѵJFЖ /ۍh g#7֭:h(7]Qi|b8}܄ x25x]q7niviEx/l} NOFH2icnV Bike-2.2.1+dfsg/source/qikea/png/site.png000066400000000000000000000015531223036517100200370ustar00rootroot00000000000000PNG  IHDR szzsRGBbKGD pHYsu0u03rtIME,FbIDATXQLU?؄ F1&K#bݪz1W4W:'Xskښ77烗9YInH9.%o;9;s#MhGO1P$zhGO1T@wʪD;z>6/[ޮ9hm.pρp*I o$S35yUooMD_ltLIo*7{o뽷z&6HJ0E$$i]'])k| 骤VI%fyucc+ ^h>sn~_囹s@C]\=o8jYIC4n%IJ­xם#*iԹE#|sb2%3ۢXj@$/i x.TU[n(4~pxh]bT suiܜuS ]$}\*0%0緀O&Z񑬪y T,rDV߾OUtj28E x'9١;`͇;0JVbRY<Q*9gX=arIENDB`ike-2.2.1+dfsg/source/qikea/png/site_add.png000066400000000000000000000020611223036517100206420ustar00rootroot00000000000000PNG  IHDRw=sRGBbKGD pHYsu0u03rtIMEMIDATHǵVQlSUnֵEy`, XL]bb0D/+fBL4q^d[ g++֎޶ヽx99H4xcپgá=o0j&d6}Ăz"F#`dKfO _"b˫XL%WE`KVlWȭoO̭E[\0`!Vn9jfjVSXliR{,}F}:%3-u8jtBAaaW6aKp%RP~cnU#u5TI<5#LݧйsNl*Ż'$km @>:_ ,C O|HnQSrEdziR9͵V"':=īCl G=CGm_}+߷璘piȆ%0 8s`|ʕdEg`l|Ɔ\N@Qa\jTxxԫX)Qd- S/>o]zDԋU Ey(U]:cSQm0X,M j&$ D۴3ZOwXħst&&|"Aԫ3G"_x܃%8 4ˢ%oҗ&f>hLpO|ЁBk.ns_D7Nn}۞ټb-גk'gGόEDurN(ka=IENDB`ike-2.2.1+dfsg/source/qikea/png/site_con.png000066400000000000000000000016451223036517100207000ustar00rootroot00000000000000PNG  IHDRw=sRGBbKGD pHYsu0u03rtIMEzb%IDATHŕKhSQ1McmS*BBA\.p QQDAQ|բ](E[XU&79.bjāsfXHRW n?FJ'U`ƾh. + @@X71y7 ,V vT|ЌRW(l]}C 5B3@܈U\(t&[$4RWp6n*6| _MB3bJFT U\pg#xV}6 @T; :|tV|{U ZabNB!XT|' tb/RdLa8 : |i}&xQ;9 f| 8۔AA*CjA&ڳ?m` %*03ѵrG q;iv/D;!lSBAe$&pf@hƠ=1~P+c[djQNAѕE'HZOE lӋ$0]W)ɯIDATHŕ[HasQv]uWWѵLQ"/ALQYIBDHR"^×FDA=iX 4/9^;{^ڼD>;??^Jf(kde$u$Y=~k}r '̈́0$la֥Ly9(3,oM]%s3kjٲo}12³ן: <׳,ZE6ܚSׄUkOc+x"ו&"j Fm^9? f տ30 @tAdDYx@!ܨ^]] |0J))D D,)5HKIyT/b'*#%aV*3k,&MQPqEٰ=^}, <7"10bGIedg鐂|1="Ȑe-8Ũ@Ξb~e#kF3*kpink t-\B/3㜯ܘTQGlC։a疳N(?GIϵ4p m&!ĚKxQ<9P!\k(#fT]li_KۏR]c-qqټ8Z$SIn>lhoj髛= Y`IENDB`ike-2.2.1+dfsg/source/qikea/png/site_mod.png000066400000000000000000000020401223036517100206660ustar00rootroot00000000000000PNG  IHDRw=sRGBbKGD pHYsu0u03rtIMEIDATHǽmlSemY1R6d58aEEaE4QфӘh$8ab"3& A$|L en#7b6f;ِ:nrkI.$ϗ<y=c3r{Ί.gjq CI7,_|)K;picm]S4|GdI]V8S;ltU^kbjv,Y\noIxfd:l6'K3ƹ( ѸGā[\n|[Th*yiQ>m/C'YR@kQV)'PU]M8}x1_">Za\ G .Yd? IVJ @@< g]%yF^@4'Oо'L@kz&=e,  (wͧyBqwO?8^S#PbSo`z&DPU5UAxK >&/, 85+(*?_?%y<ה n, IDɁ]loO|pdiZ5cXn{u)x[qzk^6H4h]Hn"7w[?I.6]_f"% Kr{*zY\@uT;|CO  QUMLΈ^t,8y^-=|lZs?2,_YR (*#a@vP_oYEihϫYq8Vx{W邇BaN<3$gdFkjo\[ O`JLCȝY{W[K0^ȣ~MӾ47Ŧ*ggIENDB`ike-2.2.1+dfsg/source/qikea/qikea.1000066400000000000000000000063751223036517100167640ustar00rootroot00000000000000.\" .\" Copyright (c) 2007 .\" Shrew Soft Inc. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" 3. Redistributions in any form must be accompanied by information on .\" how to obtain complete source code for the software and any .\" accompanying software that uses the software. The source code .\" must either be included in the distribution or be available for no .\" more than the cost of distribution plus a nominal fee, and must be .\" freely redistributable under reasonable conditions. For an .\" executable file, complete source code means the source code for all .\" modules it contains. It does not include source code for modules or .\" files that typically accompany the major components of the operating .\" system on which the executable file runs. .\" .\" THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS .\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED .\" WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR .\" NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC .\" 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. .\" .\" AUTHOR : Matthew Grooms .\" mgrooms@shrew.net .\" .\" .Dd April 12, 2010 .Dt QIKEA 1 .Os .Sh NAME .Nm qikea .Nd Internet Key Exchange Access Manager .Sh DESCRIPTION The .Nm Qt GUI application is used to manage remote Site Configurations. A remote Site Configuration describes all the parameters used to establish an IPsec VPN Client connection with a remote gateway. In addition to the creation, removal and modificaion of remote Site Configurations, the .Nm application also allows a user to launch the .Xr ikec 1 ( Shrew Soft IKE Connect ) Qt GUI application for the selected Site. .Pp .Sh RETURN VALUES The command exits with 0 on success, and non-zero on errors. .Sh FILES All user related configuration data is stored under the .Pa ~/.iked directory. Site Configuration files are stored under the .Pa ~/.iked/sites directory. Certificates and keys are are typically stored under the .Pa ~/.iked/certs directory. These directories are automatically created when the .Nm application is run for the first time by a user. .Sh SEE ALSO .Xr iked 8 .Xr ikec 1 , .Xr qikec 1 , .Sh HISTORY The .Nm program was written by Matthew Grooms ( mgrooms@shrew.net ) as part of the Shrew Soft ( http://www.shrew.net ) family of IPsec products. ike-2.2.1+dfsg/source/qikea/qikea.cpp000066400000000000000000000054601223036517100174000ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "qikea.h" _QIKEA::_QIKEA() { } _QIKEA::~_QIKEA() { } bool _QIKEA::init( qikeaRoot * setRoot ) { QDir qdir; // store our root window r = setRoot; // enumerate site configurations CONFIG config; int index = 0; while( manager.file_enumerate( config, index ) ) { printf( "adding entry for site file \'%s\'\n", config.get_id() ); QListWidgetItem * widgetItem = new QListWidgetItem( r->listWidgetSites ); widgetItem->setIcon( QIcon( ":/png/site.png" ) ); widgetItem->setText( config.get_id() ); widgetItem->setData( Qt::UserRole, config.get_id() ); widgetItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable ); // widgetItem->setRenameEnabled ( true ); config.del_all(); } return true; } ike-2.2.1+dfsg/source/qikea/qikea.h000066400000000000000000000216551223036517100170510ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #ifndef _QIKEA_H_ #define _QIKEA_H_ #include #include #include #include #include #include #include #include "../version.h" #include "config.h" #include "ui_root.h" #include "ui_site.h" #include "ui_conflict.h" #include "ui_topology.h" #include "ui_about.h" #define CONFLICT_OVERWRITE 100 #define CONFLICT_CONTINUE 101 typedef class _qikeaRoot : public QMainWindow, public Ui::qikeaRoot { Q_OBJECT QActionGroup * actionGroupView; QMenu * menuContext; QMenu * menuContextView; public: _qikeaRoot( QWidget * parent = NULL ) : QMainWindow( parent ) { setupUi( this ); actionGroupView = new QActionGroup( this ); actionGroupView->addAction( actionViewLarge ); actionGroupView->addAction( actionViewSmall ); menuView->addAction( toolBar->toggleViewAction() ); menuContext = new QMenu( listWidgetSites ); menuContextView = new QMenu( "View", listWidgetSites ); connect( listWidgetSites, SIGNAL( customContextMenuRequested( const QPoint & ) ), this, SLOT( siteContext( const QPoint & ) ) ); connect( listWidgetSites, SIGNAL( itemChanged( QListWidgetItem * ) ), this, SLOT( siteRenamed( QListWidgetItem * ) ) ); connect( listWidgetSites, SIGNAL( itemDoubleClicked ( QListWidgetItem * ) ), this, SLOT( siteConnect() ) ); connect( actionConnect, SIGNAL( triggered() ), this, SLOT( siteConnect() ) ); connect( actionAdd, SIGNAL( triggered() ), this, SLOT( siteAdd() ) ); connect( actionModify, SIGNAL( triggered() ), this, SLOT( siteModify() ) ); connect( actionDelete, SIGNAL( triggered() ), this, SLOT( siteDelete() ) ); connect( actionRename, SIGNAL( triggered() ), this, SLOT( siteRename() ) ); connect( actionViewLarge, SIGNAL( triggered() ), this, SLOT( showViewLarge() ) ); connect( actionViewSmall, SIGNAL( triggered() ), this, SLOT( showViewSmall() ) ); connect( actionImport, SIGNAL( triggered() ), this, SLOT( siteImport() ) ); connect( actionExport, SIGNAL( triggered() ), this, SLOT( siteExport() ) ); connect( actionAbout, SIGNAL( triggered() ), this, SLOT( showAbout() ) ); connect( actionExit, SIGNAL( triggered() ), this, SLOT( close() ) ); } void fileConflict( QString & path, QString & name ); private slots: void showViewLarge(); void showViewSmall(); void siteContext( const QPoint & pos ); void siteConnect(); void siteAdd(); void siteModify(); void siteDelete(); void siteRename(); void siteRenamed( QListWidgetItem * ); void siteImport(); void siteExport(); void showAbout(); }qikeaRoot; typedef class _qikeaSite : public QDialog, public Ui::qikeaSite { Q_OBJECT QString pathCAFile; QString pathCertFile; QString pathPKeyFile; public: _qikeaSite( QWidget * parent = NULL ) : QDialog( parent ) { setupUi( this ); init(); connect( buttonSave, SIGNAL( clicked() ), this, SLOT( verify() ) ); connect( buttonCancel, SIGNAL( clicked() ), this, SLOT( reject() ) ); connect( checkBoxAddressAuto, SIGNAL( clicked() ), this, SLOT( updateAddressAuto() ) ); connect( checkBoxDNSEnable, SIGNAL( clicked() ), this, SLOT( updateNameResolution() ) ); connect( checkBoxDNSAuto, SIGNAL( clicked() ), this, SLOT( updateNameResolution() ) ); connect( checkBoxSuffixAuto, SIGNAL( clicked() ), this, SLOT( updateNameResolution() ) ); connect( checkBoxLocalIDOption, SIGNAL( clicked() ), this, SLOT( updateLocalID() ) ); connect( checkBoxRemoteIDOption, SIGNAL( clicked() ), this, SLOT( updateRemoteID() ) ); connect( checkBoxPolicyAuto, SIGNAL( clicked() ), this, SLOT( updatePolicy() ) ); connect( comboBoxAuthMethod, SIGNAL( activated( int ) ), this, SLOT( updateAuthentication() ) ); connect( comboBoxConfigMethod, SIGNAL( activated( int ) ), this, SLOT( updateConfigMethod() ) ); connect( comboBoxAddressMethod, SIGNAL( activated( int ) ), this, SLOT( updateAddressMethod() ) ); connect( comboBoxFragMode, SIGNAL( activated( int ) ), this, SLOT( updateClient() ) ); connect( comboBoxNATTMode, SIGNAL( activated( int ) ), this, SLOT( updateClient() ) ); connect( comboBoxLocalIDType, SIGNAL( activated( int ) ), this, SLOT( updateLocalID() ) ); connect( comboBoxRemoteIDType, SIGNAL( activated( int ) ), this, SLOT( updateRemoteID() ) ); connect( comboBoxP1Exchange, SIGNAL( activated( int ) ), this, SLOT( updatePhase1() ) ); connect( comboBoxP1Cipher, SIGNAL( activated( int ) ), this, SLOT( updatePhase1() ) ); connect( comboBoxP2Transform, SIGNAL( activated( int ) ), this, SLOT( updatePhase2() ) ); connect( pushButtonPolicyAdd, SIGNAL( clicked() ), this, SLOT( policyAdd() ) ); connect( pushButtonPolicyMod, SIGNAL( clicked() ), this, SLOT( policyModify() ) ); connect( pushButtonPolicyDel, SIGNAL( clicked() ), this, SLOT( policyDelete() ) ); connect( toolButtonCAFile, SIGNAL( clicked() ), this, SLOT( inputCAFile() ) ); connect( toolButtonCertFile, SIGNAL( clicked() ), this, SLOT( inputCertFile() ) ); connect( toolButtonPKeyFile, SIGNAL( clicked() ), this, SLOT( inputPKeyFile() ) ); connect( treeWidgetPolicies, SIGNAL( itemSelectionChanged() ), this, SLOT( updatePolicy() ) ); } void init(); bool load( CONFIG & config ); bool save( CONFIG & config ); private slots: bool verify(); void policyAdd(); void policyModify(); void policyDelete(); void updateConfigMethod(); void updateAddressAuto(); void updateAddressMethod(); void updateGeneral( bool adflt, bool mdflt ); void updateClient(); void updateNameResolution(); void updateAuthMethod(); void updateAuthentication(); void updateLocalID(); void updateRemoteID(); void updatePhase1(); void updatePhase2(); void updatePolicy(); void selectLocalID(); void selectRemoteID(); void inputCAFile(); void inputCertFile(); void inputPKeyFile(); }qikeaSite; typedef class _qikeaConflict : public QDialog, public Ui::qikeaConflict { Q_OBJECT public: _qikeaConflict( QWidget * parent = NULL ) : QDialog( parent ) { setupUi( this ); connect( buttonContinue, SIGNAL( clicked() ), this, SLOT( accept() ) ); connect( buttonOverwrite, SIGNAL( clicked() ), this, SLOT( reject() ) ); } private slots: }qikeaConflict; typedef class _qikeaTopology : public QDialog, public Ui::qikeaTopology { Q_OBJECT public: _qikeaTopology( QWidget * parent = NULL ) : QDialog( parent ) { setupUi( this ); connect( buttonOk, SIGNAL( clicked() ), this, SLOT( verify() ) ); connect( buttonCancel, SIGNAL( clicked() ), this, SLOT( reject() ) ); } private slots: bool verify(); }qikeaTopology; typedef class _qikeaAbout : public QDialog, public Ui::qikeaAbout { Q_OBJECT public: _qikeaAbout( QWidget * parent = NULL ) : QDialog( parent ) { setupUi( this ); connect( buttonOk, SIGNAL( clicked() ), this, SLOT( accept() ) ); } private slots: }qikeaAbout; typedef class _QIKEA { protected: qikeaRoot * r; public: _QIKEA(); ~_QIKEA(); CONFIG_MANAGER manager; bool init( qikeaRoot * setRoot ); }QIKEA; extern QIKEA qikea; #endif ike-2.2.1+dfsg/source/qikea/qikea.pro000066400000000000000000000007531223036517100174160ustar00rootroot00000000000000TEMPLATE = app LANGUAGE = C++ CONFIG += qt warn_on release QT += qtgui LIBS += ../libidb/libidb.a ../libith/libith.a ../liblog/liblog.a DEFINES += OPT_NATT UNIX INCLUDEPATH += . ./.. ../libidb ../libith ../liblog HEADERS = \ config.h \ ikea.h SOURCES = \ config.cpp \ ikea.cpp \ main.cpp \ root.cpp \ site.cpp FORMS = \ site.ui \ root.ui \ topology.ui \ about.ui \ conflict.ui RESOURCES = \ ikea.qrc unix { UI_DIR = .ui MOC_DIR = .moc OBJECTS_DIR = .obj } ike-2.2.1+dfsg/source/qikea/qikea.qrc000066400000000000000000000006371223036517100174040ustar00rootroot00000000000000 png/ikea.png png/logo_ssoft.png png/policy_exc.png png/policy_inc.png png/site.png png/site_add.png png/site_con.png png/site_del.png png/site_mod.png ike-2.2.1+dfsg/source/qikea/root.cpp000066400000000000000000000232131223036517100172650ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "qikea.h" bool file_to_bdata( QString path, BDATA & bdata ) { bdata.del(); FILE * fp = fopen( path.toAscii(), "rb" ); if( fp == NULL ) return false; while( true ) { int next = fgetc( fp ); if( next == EOF ) break; bdata.add( next, 1 ); } fclose( fp ); return ( bdata.size() > 0 ); } bool bdata_to_file( BDATA & bdata, QString path ) { FILE * fp = fopen( path.toAscii(), "wb" ); if( fp == NULL ) return false; size_t count = bdata.size(); size_t index = 0; for( ; index < count; index++ ) fputc( bdata.buff()[ index ], fp ); fclose( fp ); return true; } void site_name_mangle( QString & name ) { // mangle name if duplicate QString tmpName = name; CONFIG tmpConfig; tmpConfig.set_id( name.toAscii() ); int index = 2; while( qikea.manager.file_vpn_load( tmpConfig ) ) { name = tmpName; name += QString( " (" ); name += QString::number( index++ ); name += QString( ")" ); tmpConfig.set_id( name.toAscii() ); } } void _qikeaRoot::fileConflict( QString & path, QString & name ) { QString tmpName = name; QString tmpPath = path; while( QFile::exists( tmpPath ) ) { qikeaConflict fc( this ); fc.lineConflictName->setText( name ); if( fc.exec() == QDialog::Rejected ) break; name = fc.lineConflictName->text(); tmpPath = path + "/" + name; } } void _qikeaRoot::siteContext( const QPoint & pos ) { QListWidgetItem * i = listWidgetSites->itemAt( pos ); menuContextView->clear(); menuContextView->addAction( actionViewLarge ); menuContextView->addAction( actionViewSmall ); menuContext->clear(); if( i != NULL ) { menuContext->addAction( actionConnect ); menuContext->addSeparator(); } menuContext->addMenu( menuContextView ); menuContext->addSeparator(); menuContext->addSeparator(); menuContext->addAction( actionAdd ); if( i != NULL ) { menuContext->addAction( actionDelete ); menuContext->addAction( actionRename ); menuContext->addSeparator(); menuContext->addAction( actionModify ); } // // FIXME : If we don't change the position // value the popup immediately dissapears // when the user right clicks. Why? // QPoint mpos( listWidgetSites->mapToGlobal( pos ) ); mpos.setX( mpos.x() + 1 ); menuContext->popup( mpos ); } void _qikeaRoot::showViewLarge() { listWidgetSites->setViewMode( QListView::IconMode ); } void _qikeaRoot::showViewSmall() { listWidgetSites->setViewMode( QListView::ListMode ); } void _qikeaRoot::siteConnect() { QListWidgetItem * i = listWidgetSites->currentItem(); if( i == NULL ) return; // launch ikec with site name as parameter #ifndef __APPLE__ QStringList args; args << "-r"; args << i->text(); QProcess * proc = new QProcess( this ); proc->start( "qikec", args ); #else QStringList args; args << "/Applications/Shrew Soft VPN Client Connect.app"; args << "--args"; args << "-r"; args << i->text(); QProcess * proc = new QProcess( this ); proc->start( "open", args ); #endif } void _qikeaRoot::siteAdd() { qikeaSite s( this ); if( s.exec() != QDialog::Accepted ) return; // save site config CONFIG config; config.set_number( "version", CONFIG_VERSION ); s.save( config ); QString siteName = s.lineEditHost->text(); // mangle name if duplicate site_name_mangle( siteName ); config.set_id( siteName.toAscii() ); // write site config qikea.manager.file_vpn_save( config ); // create icon for site QListWidgetItem * i = new QListWidgetItem( listWidgetSites ); if( i == NULL ) return; i->setIcon( QIcon( ":/png/site.png" ) ); i->setText( siteName ); i->setData( Qt::UserRole, siteName ); i->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable ); i->setSelected( true ); listWidgetSites->editItem( i ); } void _qikeaRoot::siteModify() { QListWidgetItem * i = listWidgetSites->currentItem(); if( i == NULL ) return; // load site config CONFIG config; config.set_id( i->text().toAscii() ); qikea.manager.file_vpn_load( config ); // create site modal dialog qikeaSite s( this ); s.load( config ); if( s.exec() == QDialog::Accepted ) { // save modified site config s.save( config ); qikea.manager.file_vpn_save( config ); } } void _qikeaRoot::siteDelete() { QListWidgetItem * i = listWidgetSites->currentItem(); if( i == NULL ) return; QMessageBox m; if( m.question( this, "Confirm Delete", "Are you sure you want to delete this site?", QMessageBox::Yes, QMessageBox::Cancel ) != QMessageBox::Yes ) return; CONFIG config; config.set_id( i->text().toAscii() ); qikea.manager.file_vpn_del( config ); delete i; } void _qikeaRoot::siteRename() { QListWidgetItem * i = listWidgetSites->currentItem(); if( i == NULL ) return; listWidgetSites->editItem( i ); } void _qikeaRoot::siteRenamed( QListWidgetItem * i ) { QString oldName = i->data( Qt::UserRole ).toString(); QString modName = i->text(); if( !oldName.length() || ( oldName == modName ) ) return; if( !modName.length() ) { i->setText( oldName ); return; } site_name_mangle( modName ); CONFIG config; config.set_id( oldName.toAscii() ); qikea.manager.file_vpn_load( config ); qikea.manager.file_vpn_del( config ); config.set_id( modName.toAscii() ); qikea.manager.file_vpn_save( config ); i->setText( modName ); i->setData( Qt::UserRole, modName ); } void _qikeaRoot::siteImport() { // get the input path QString types( "Shrew Soft VPN file (*.vpn);;" "Cisco PCF file (*.pcf);;" "All files (*)" ); QString loadPath = QFileDialog::getOpenFileName( this, "Select the Import File", QDir::homePath(), types ); if( !loadPath.length() ) return; // load the site config CONFIG config; bool need_certs = false; if( !loadPath.contains( ".pcf", Qt::CaseInsensitive ) ) qikea.manager.file_vpn_load( config, loadPath.toAscii(), false ); else qikea.manager.file_pcf_load( config, loadPath.toAscii(), need_certs ); // determine file name QFileInfo fileInfo( loadPath ); QString siteName = fileInfo.baseName(); // mangle name if duplicate site_name_mangle( siteName ); // save the site config config.set_id( siteName.toAscii() ); qikea.manager.file_vpn_save( config ); // create icon for site QListWidgetItem * i = new QListWidgetItem( listWidgetSites ); if( i == NULL ) return; i->setIcon( QIcon( ":/png/site.png" ) ); i->setText( siteName ); i->setData( Qt::UserRole, siteName ); i->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable ); i->setSelected( true ); if( need_certs ) { QMessageBox m; m.warning( this, "Site Import Warning", "The Cisco site configuration was imported but uses " "an RSA authentication method. You will need to import " "a certificate manually to complete the configuration.", QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton ); } listWidgetSites->editItem( i ); } void _qikeaRoot::siteExport() { QListWidgetItem * i = listWidgetSites->currentItem(); if( i == NULL ) return; // load site config CONFIG config; config.set_id( i->text().toAscii() ); qikea.manager.file_vpn_load( config ); // get the output path QString types( "Site Configurations files (*.vpn);;" "All files (*)" ); QString savePath = QFileDialog::getSaveFileName( this, "Select the VPN Export File", QDir::homePath() + "/" + i->text() + ".vpn", types ); if( !savePath.length() ) return; qikea.manager.file_vpn_save( config, savePath.toAscii() ); } void _qikeaRoot::showAbout() { qikeaAbout a( this ); QString Major, Minor, Build; Major.setNum( CLIENT_VER_MAJ ); Minor.setNum( CLIENT_VER_MIN ); Build.setNum( CLIENT_VER_BLD ); a.textLabelVersion->setText( "Ver " + Major + "." + Minor + "." + Build ); a.exec(); } ike-2.2.1+dfsg/source/qikea/root.ui000066400000000000000000000167511223036517100171310ustar00rootroot00000000000000 Matthew Grooms qikeaRoot 0 0 380 270 Shrew Soft VPN Access Manager :/png/ikea.png:/png/ikea.png Qt::CustomContextMenu QAbstractItemView::EditKeyPressed QListView::Static QListView::Adjust QListView::IconMode true true 0 0 380 24 &File &Edit &Help &View Qt::TabFocus toolBar false true 32 32 Qt::ToolButtonTextBesideIcon TopToolBarArea false :/png/site_con.png:/png/site_con.png &Connect Connect Connect using this site configuration :/png/site_add.png:/png/site_add.png &Add Add Add a new site configuration :/png/site_del.png:/png/site_del.png &Delete Delete Delete this site configuration :/png/site_mod.png:/png/site_mod.png &Modify Modify Modify this site configuration Import Export Exit Rename About Large Icons true true Large Icons &Large Icons Large Icon View true Small Icons &Small Icons Small Icon View Details &Details Detailed View true true Toolbar &Toolbar ike-2.2.1+dfsg/source/qikea/site.cpp000066400000000000000000001526571223036517100172650ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "qikea.h" #define EXCH_AGGR_MODE 0 #define EXCH_MAIN_MODE 1 #define AUTH_HYBRID_RSA_XAUTH 0 #define AUTH_HYBRID_GRP_XAUTH 1 #define AUTH_MUTUAL_RSA_XAUTH 2 #define AUTH_MUTUAL_PSK_XAUTH 3 #define AUTH_MUTUAL_RSA 4 #define AUTH_MUTUAL_PSK 5 #define AMTXT_VIRTUAL "Use a virtual adapter and assigned address" #define AMTXT_RANDOM "Use a virtual adapter and random address" #define AMTXT_DIRECT "Use an existing adapter and current address" #define IDTXT_NONE "No Identity" #define IDTXT_ANY "Any" #define IDTXT_ASN1 "ASN.1 Distinguished Name" #define IDTXT_FQDN "Fully Qualified Domain Name" #define IDTXT_UFQDN "User Fully Qualified Domain Name" #define IDTXT_ADDR "IP Address" #define IDTXT_KEYID "Key Identifier" #define TREE_INCLUDE ( QTreeWidgetItem::UserType + 1 ) #define TREE_EXCLUDE ( QTreeWidgetItem::UserType + 2 ) bool combobox_setbytext( QString text, QComboBox * cbox ) { long index = 0; long count = cbox->count(); for( ; index < count; index++ ) { if( text == cbox->itemText( index ) ) { cbox->setCurrentIndex( index ); return true; } } return false; } bool dhgrp_to_string( long & dhgrp, QString & string ) { switch( dhgrp ) { case -1: string = "disabled"; break; case 0: string = "auto"; break; case 1: string = "group 1"; break; case 2: string = "group 2"; break; case 5: string = "group 5"; break; case 14: string = "group 14"; break; case 15: string = "group 15"; break; case 16: string = "group 16"; break; case 17: string = "group 17"; break; case 18: string = "group 18"; break; default: return false; } return true; } bool string_to_dhgrp( QString & string, long & dhgrp ) { if( string == "disabled" ) dhgrp = -1; if( string == "auto" ) dhgrp = 0; if( string == "group 1" ) dhgrp = 1; if( string == "group 2" ) dhgrp = 2; if( string == "group 5" ) dhgrp = 5; if( string == "group 14" ) dhgrp = 14; if( string == "group 15" ) dhgrp = 15; if( string == "group 16" ) dhgrp = 16; if( string == "group 17" ) dhgrp = 17; if( string == "group 18" ) dhgrp = 18; return true; } void _qikeaSite::init() { comboBoxConfigMethod->setCurrentIndex( 1 ); lineEditAddress->setInputMask( "009 . 009 . 009 . 009" ); lineEditAddress->setText( "0.0.0.0" ); lineEditNetmask->setInputMask( "009 . 009 . 009 . 009" ); lineEditNetmask->setText( "255.255.255.255" ); lineEditDNSServer1->setInputMask( "009 . 009 . 009 . 009" ); lineEditDNSServer1->setText( "0.0.0.0" ); lineEditDNSServer2->setInputMask( "009 . 009 . 009 . 009" ); lineEditDNSServer2->setText( "0.0.0.0" ); lineEditDNSServer3->setInputMask( "009 . 009 . 009 . 009" ); lineEditDNSServer3->setText( "0.0.0.0" ); lineEditDNSServer4->setInputMask( "009 . 009 . 009 . 009" ); lineEditDNSServer4->setText( "0.0.0.0" ); #ifdef OPT_NATT textLabelNATTMode->setEnabled( true ); comboBoxNATTMode->setEnabled( true ); textLabelNATTPort->setEnabled( true ); lineEditNATTPort->setEnabled( true ); textLabelNATTRate->setEnabled( true ); lineEditNATTRate->setEnabled( true ); textLabelNATTSecs->setEnabled( true ); combobox_setbytext( "enable", comboBoxNATTMode ); #endif // update dialog updateGeneral( false, false ); updateAuthentication(); updatePhase1(); updatePhase2(); updatePolicy(); } void _qikeaSite::policyAdd() { qikeaTopology t( this ); if( t.exec() == QDialog::Rejected ) return; // address and netmask QString address = t.lineEditAddress->text(); address = address.replace( ' ', "" ); QString netmask = t.lineEditNetmask->text(); netmask = netmask.replace( ' ', "" ); QString text = address + " / " + netmask; // create item if( !t.comboBoxType->currentIndex() ) { QTreeWidgetItem * i = new QTreeWidgetItem( treeWidgetPolicies, TREE_INCLUDE ); i->setText( 0, text ); i->setIcon( 0, QIcon( ":/png/policy_inc.png" ) ); } else { QTreeWidgetItem * i = new QTreeWidgetItem( treeWidgetPolicies, TREE_EXCLUDE ); i->setText( 0, text ); i->setIcon( 0, QIcon( ":/png/policy_exc.png" ) ); } } void _qikeaSite::policyModify() { QTreeWidgetItem * i = treeWidgetPolicies->currentItem(); if( i == NULL ) return; QString text = i->text( 0 ); QString address = text.section( '/', 0, 0 ); QString netmask = text.section( '/', 1, 1 ); address = address.replace( ' ', "" ); netmask = netmask.replace( ' ', "" ); qikeaTopology t( this ); t.lineEditAddress->setText( address ); t.lineEditNetmask->setText( netmask ); if( i->type() == TREE_INCLUDE ) t.comboBoxType->setCurrentIndex( 0 ); else t.comboBoxType->setCurrentIndex( 1 ); if( t.exec() == QDialog::Rejected ) return; delete i; // address and netmask text = t.lineEditAddress->text(); text += " / "; text += t.lineEditNetmask->text(); // set icon if( !t.comboBoxType->currentIndex() ) { i = new QTreeWidgetItem( treeWidgetPolicies, TREE_INCLUDE ); i->setText( 0, text ); i->setIcon( 0, QIcon( ":/png/policy_inc.png" ) ); } else { i = new QTreeWidgetItem( treeWidgetPolicies, TREE_EXCLUDE ); i->setText( 0, text ); i->setIcon( 0, QIcon( ":/png/policy_exc.png" ) ); } } void _qikeaSite::policyDelete() { QTreeWidgetItem * i = treeWidgetPolicies->currentItem(); if( i != NULL ) delete i; } bool _qikeaSite::load( CONFIG & config ) { QString string; char text[ MAX_CONFSTRING ]; long numb; // remote name or address if( config.get_string( "network-host", text, MAX_CONFSTRING, 0 ) ) lineEditHost->setText( text ); // remote ike port ( default 500 ) if( config.get_number( "network-ike-port", &numb ) ) lineEditPort->setText( QString::number( numb, 10 ) ); // remote config method ( default pull ) if( config.get_string( "client-auto-mode", text, MAX_CONFSTRING, 0 ) ) { if( !strcmp( text, "disabled" ) ) comboBoxConfigMethod->setCurrentIndex( 0 ); if( !strcmp( text, "pull" ) ) comboBoxConfigMethod->setCurrentIndex( 1 ); if( !strcmp( text, "push" ) ) comboBoxConfigMethod->setCurrentIndex( 2 ); if( !strcmp( text, "dhcp" ) ) comboBoxConfigMethod->setCurrentIndex( 3 ); } // update dialog updateGeneral( false, false ); // local adapter mode ( default virtual ) if( config.get_string( "client-iface", text, MAX_CONFSTRING, 0 ) ) { if( !strcmp( text, "virtual" ) ) combobox_setbytext( AMTXT_VIRTUAL, comboBoxAddressMethod ); if( !strcmp( text, "random" ) ) combobox_setbytext( AMTXT_RANDOM, comboBoxAddressMethod ); if( !strcmp( text, "direct" ) ) combobox_setbytext( AMTXT_DIRECT, comboBoxAddressMethod ); } if( !strcmp( text, "virtual" ) || !strcmp( text, "random" ) ) { // virtual adapter mtu numb = 0; if( config.get_number( "network-mtu-size", &numb ) ) lineEditMTU->setText( QString::number( numb, 10 ) ); // virtual adapter address numb = 0; config.get_number( "client-addr-auto", &numb ); if( numb ) { // automatic checkBoxAddressAuto->setChecked( true ); } else { // manual checkBoxAddressAuto->setChecked( false ); // adapter address if( config.get_string( "client-ip-addr", text, MAX_CONFSTRING, 0 ) ) lineEditAddress->setText( text ); // adapter netmask if( config.get_string( "client-ip-mask", text, MAX_CONFSTRING, 0 ) ) lineEditNetmask->setText( text ); } } #ifdef OPT_NATT // nat traversal mode ( default enabled ) if( config.get_string( "network-natt-mode", text, MAX_CONFSTRING, 0 ) ) combobox_setbytext( text, comboBoxNATTMode ); // natt not disabled if( comboBoxNATTMode->currentIndex() ) { // nat traversal port ( default 4500 ) if( config.get_number( "network-natt-port", &numb ) ) lineEditNATTPort->setText( QString::number( numb, 10 ) ); // nat traversal keep alive rate ( default 30 ) if( config.get_number( "network-natt-rate", &numb ) ) lineEditNATTRate->setText( QString::number( numb, 10 ) ); } #endif // ike fragment mode ( default enabled ) if( config.get_string( "network-frag-mode", text, MAX_CONFSTRING, 0 ) ) combobox_setbytext( text, comboBoxFragMode ); // ike frag not disabled if( comboBoxFragMode->currentIndex() ) { // max packet size if( config.get_number( "network-frag-size", &numb ) ) lineEditFragSize->setText( QString::number( numb, 10 ) ); } // dead peer detection enabled ( default enabled ) numb = 1; config.get_number( "network-dpd-enable", &numb ); if( numb ) checkBoxDPD->setChecked( true ); else checkBoxDPD->setChecked( false ); // isakmp failure notifications enabled ( default enabled ) numb = 1; config.get_number( "network-notify-enable", &numb ); if( numb ) checkBoxNotify->setChecked( true ); else checkBoxNotify->setChecked( false ); // login banner enabled ( default enabled ) numb = 1; config.get_number( "client-banner-enable", &numb ); if( numb ) checkBoxBanner->setChecked( true ); else checkBoxBanner->setChecked( false ); // dns used ( default used ) numb = 1; config.get_number( "client-dns-used", &numb ); if( !numb ) { // disabled checkBoxDNSEnable->setChecked( false ); } else { // enabled checkBoxDNSEnable->setChecked( true ); // dns settings ( default automatic ) numb = 1; config.get_number( "client-dns-auto", &numb ); if( numb ) { // automatic dns server addresses checkBoxDNSAuto->setChecked( true ); } else { // manual dns server addresses checkBoxDNSAuto->setChecked( false ); long index = 0; if( config.get_string( "client-dns-addr", text, MAX_CONFSTRING, index++ ) ) lineEditDNSServer1->setText( text ); if( config.get_string( "client-dns-addr", text, MAX_CONFSTRING, index++ ) ) lineEditDNSServer2->setText( text ); if( config.get_string( "client-dns-addr", text, MAX_CONFSTRING, index++ ) ) lineEditDNSServer3->setText( text ); if( config.get_string( "client-dns-addr", text, MAX_CONFSTRING, index++ ) ) lineEditDNSServer4->setText( text ); } numb = 1; config.get_number( "client-dns-suffix-auto", &numb ); if( numb ) { // automatic dns default suffix checkBoxSuffixAuto->setChecked( true ); } else { // manual dns default suffix checkBoxSuffixAuto->setChecked( false ); if( config.get_string( "client-dns-suffix", text, MAX_CONFSTRING, 0 ) ) lineEditDNSSuffix->setText( text ); } } // update dialog updateGeneral( false, false ); // authentication mode ( default hybrid rsa xauth ) if( config.get_string( "auth-method", text, MAX_CONFSTRING, 0 ) ) { if( !strcmp( "hybrid-rsa-xauth", text ) ) comboBoxAuthMethod->setCurrentIndex( 0 ); if( !strcmp( "hybrid-grp-xauth", text ) ) comboBoxAuthMethod->setCurrentIndex( 1 ); if( !strcmp( "mutual-rsa-xauth", text ) ) comboBoxAuthMethod->setCurrentIndex( 2 ); if( !strcmp( "mutual-psk-xauth", text ) ) comboBoxAuthMethod->setCurrentIndex( 3 ); if( !strcmp( "mutual-rsa", text ) ) comboBoxAuthMethod->setCurrentIndex( 4 ); if( !strcmp( "mutual-psk", text ) ) comboBoxAuthMethod->setCurrentIndex( 5 ); } // update dialog updateAuthMethod(); // local identity type if( config.get_string( "ident-client-type", text, MAX_CONFSTRING, 0 ) ) { if( !strcmp( "none", text ) ) combobox_setbytext( IDTXT_NONE, comboBoxLocalIDType ); if( !strcmp( "asn1dn", text ) ) combobox_setbytext( IDTXT_ASN1, comboBoxLocalIDType ); if( !strcmp( "fqdn", text ) ) combobox_setbytext( IDTXT_FQDN, comboBoxLocalIDType ); if( !strcmp( "ufqdn", text ) ) combobox_setbytext( IDTXT_UFQDN, comboBoxLocalIDType ); if( !strcmp( "address", text ) ) combobox_setbytext( IDTXT_ADDR, comboBoxLocalIDType ); if( !strcmp( "keyid", text ) ) combobox_setbytext( IDTXT_KEYID, comboBoxLocalIDType ); } // local identity data if( config.get_string( "ident-client-data", text, MAX_CONFSTRING, 0 ) ) { lineEditLocalIDData->setText( text ); checkBoxLocalIDOption->setChecked( false ); } // remote identity type if( config.get_string( "ident-server-type", text, MAX_CONFSTRING, 0 ) ) { if( !strcmp( "any", text ) ) combobox_setbytext( IDTXT_ANY, comboBoxRemoteIDType ); if( !strcmp( "asn1dn", text ) ) combobox_setbytext( IDTXT_ASN1, comboBoxRemoteIDType ); if( !strcmp( "fqdn", text ) ) combobox_setbytext( IDTXT_FQDN, comboBoxRemoteIDType ); if( !strcmp( "ufqdn", text ) ) combobox_setbytext( IDTXT_UFQDN, comboBoxRemoteIDType ); if( !strcmp( "address", text ) ) combobox_setbytext( IDTXT_ADDR, comboBoxRemoteIDType ); if( !strcmp( "keyid", text ) ) combobox_setbytext( IDTXT_KEYID, comboBoxRemoteIDType ); } // remote identity data if( config.get_string( "ident-server-data", text, MAX_CONFSTRING, 0 ) ) { lineEditRemoteIDData->setText( text ); checkBoxRemoteIDOption->setChecked( false ); } // credentials if( config.get_string( "auth-server-cert-name", text, MAX_CONFSTRING, 0 ) ) lineEditCAName->setText( text ); if( config.get_string( "auth-client-cert-name", text, MAX_CONFSTRING, 0 ) ) lineEditCertName->setText( text ); if( config.get_string( "auth-client-key-name", text, MAX_CONFSTRING, 0 ) ) lineEditPKeyName->setText( text ); BDATA psk; if( config.get_binary( "auth-mutual-psk", psk ) ) { psk.add( "", 1 ); lineEditPSK->setText( psk.text() ); } // update dialog updateAuthentication(); // phase1 exchange type ( default main ) if( config.get_string( "phase1-exchange", text, MAX_CONFSTRING, 0 ) ) { if( !strcmp( text, "aggressive" ) ) comboBoxP1Exchange->setCurrentIndex( EXCH_AGGR_MODE ); if( !strcmp( text, "main" ) ) comboBoxP1Exchange->setCurrentIndex( EXCH_MAIN_MODE ); } // update dialog updatePhase1(); // phase1 dh group ( default auto ) numb = 0; config.get_number( "phase1-dhgroup", &numb ); if( dhgrp_to_string( numb, string ) ) combobox_setbytext( string, comboBoxP1DHGroup ); // phase1 cipher algorithm ( default auto ) if( config.get_string( "phase1-cipher", text, MAX_CONFSTRING, 0 ) ) combobox_setbytext( text, comboBoxP1Cipher ); // phase1 cipher key length ( default auto ) if( config.get_number( "phase1-keylen", &numb ) ) { snprintf( text, 5, "%lu", numb ); combobox_setbytext( text, comboBoxP1Keylen ); } // phase1 hash algorithm ( default auto ) if( config.get_string( "phase1-hash", text, MAX_CONFSTRING, 0 ) ) combobox_setbytext( text, comboBoxP1Hash ); // phase1 key life time ( default 86400 ) if( config.get_number( "phase1-life-secs", &numb ) ) lineEditP1LifeTime->setText( QString::number( numb, 10 ) ); // phase1 key life data ( default 3600 ) if( config.get_number( "phase1-life-kbytes", &numb ) ) lineEditP1LifeData->setText( QString::number( numb, 10 ) ); // phase1 checkpoint vendor option numb = 1; config.get_number( "vendor-chkpt-enable", &numb ); if( numb ) checkBoxCheckpointID->setChecked( true ); else checkBoxCheckpointID->setChecked( false ); // phase2 trasform algorithm ( default auto ) if( config.get_string( "phase2-transform", text, MAX_CONFSTRING, 0 ) ) combobox_setbytext( text, comboBoxP2Transform ); // phase2 transform key length ( default auto ) if( config.get_number( "phase2-keylen", &numb ) ) { snprintf( text, 5, "%lu", numb ); combobox_setbytext( text, comboBoxP2Keylen ); } // phase2 hmac algorithm ( default auto ) if( config.get_string( "phase2-hmac", text, MAX_CONFSTRING, 0 ) ) combobox_setbytext( text, comboBoxP2HMAC ); // phase2 pfs group ( default disabled ) numb = -1; config.get_number( "phase2-pfsgroup", &numb ); if( dhgrp_to_string( numb, string ) ) combobox_setbytext( string, comboBoxP2PFSGroup ); // ipcomp transform algorithm if( config.get_string( "ipcomp-transform", text, MAX_CONFSTRING, 0 ) ) combobox_setbytext( text, comboBoxP2Compress ); // phase2 key life time if( config.get_number( "phase2-life-secs", &numb ) ) lineEditP2LifeTime->setText( QString::number( numb, 10 ) ); // phase2 key life data if( config.get_number( "phase2-life-kbytes", &numb ) ) lineEditP2LifeData->setText( QString::number( numb, 10 ) ); // policy level option ( default auto ) if( config.get_string( "policy-level", text, MAX_CONFSTRING, 0 ) ) combobox_setbytext( text, comboBoxPolicyLevel ); // policy nailed sa option ( defailt off ) numb = 0; config.get_number( "policy-nailed", &numb ); if( numb ) checkBoxPolicyNailed->setChecked( true ); else checkBoxPolicyNailed->setChecked( false ); // policy configuration ( default auto ) numb = 1; config.get_number( "policy-list-auto", &numb ); if( !numb ) { // manual checkBoxPolicyAuto->setChecked( false ); // topology exclude list long index = 0; while( config.get_string( "policy-list-exclude", text, MAX_CONFSTRING, index++ ) ) { QTreeWidgetItem * i = new QTreeWidgetItem( treeWidgetPolicies, TREE_EXCLUDE ); i->setText( 0, text ); i->setIcon( 0, QIcon( ":/png/policy_exc.png" ) ); } // topology include list index = 0; while( config.get_string( "policy-list-include", text, MAX_CONFSTRING, index++ ) ) { QTreeWidgetItem * i = new QTreeWidgetItem( treeWidgetPolicies, TREE_INCLUDE ); i->setText( 0, text ); i->setIcon( 0, QIcon( ":/png/policy_inc.png" ) ); } } // update dialog updatePhase1(); updatePhase2(); updatePolicy(); return true; } bool _qikeaSite::save( CONFIG & config ) { // remote name or address config.set_string( "network-host", lineEditHost->text().toAscii(), lineEditHost->text().length() ); // remote ike port config.set_number( "network-ike-port", lineEditPort->text().toLong() ); // remote config method switch( comboBoxConfigMethod->currentIndex() ) { case 0: // disabled config.set_string( "client-auto-mode", "disabled", strlen( "disabled" ) ); break; case 1: // ike config pull config.set_string( "client-auto-mode", "pull", strlen( "pull" ) ); break; case 2: // ike config push config.set_string( "client-auto-mode", "push", strlen( "push" ) ); break; case 3: // dhcp over ipsec config.set_string( "client-auto-mode", "dhcp", strlen( "dhcp" ) ); break; } // local adapter mode QString amode = comboBoxAddressMethod->currentText(); if( !amode.compare( AMTXT_VIRTUAL ) ) { // direct mode config.set_string( "client-iface", "virtual", strlen( "virtual" ) ); } if( !amode.compare( AMTXT_RANDOM ) ) { // direct mode config.set_string( "client-iface", "random", strlen( "random" ) ); } if( !amode.compare( AMTXT_DIRECT ) ) { // direct mode config.set_string( "client-iface", "direct", strlen( "direct" ) ); } if( !amode.compare( AMTXT_VIRTUAL ) || !amode.compare( AMTXT_RANDOM ) ) { // adapter mtu config.set_number( "network-mtu-size", lineEditMTU->text().toLong() ); // adapter address if( checkBoxAddressAuto->isChecked() ) { // automatic config.set_number( "client-addr-auto", 1 ); } else { // manual config.set_number( "client-addr-auto", 0 ); // adapter address QString Address = lineEditAddress->text(); Address = Address.replace( ' ', "" ); config.set_string( "client-ip-addr", Address.toAscii(), Address.length() ); // adapter netmask QString Netmask = lineEditNetmask->text(); Netmask = Netmask.replace( ' ', "" ); config.set_string( "client-ip-mask", Netmask.toAscii(), Netmask.length() ); } } #ifdef OPT_NATT // nat traversal mode config.set_string( "network-natt-mode", comboBoxNATTMode->currentText().toAscii(), comboBoxNATTMode->currentText().length() ); // natt not disabled if( comboBoxNATTMode->currentIndex() ) { // nat traversal port config.set_number( "network-natt-port", lineEditNATTPort->text().toLong() ); // nat traversal keep alive rate config.set_number( "network-natt-rate", lineEditNATTRate->text().toLong() ); } #endif // ike fragment mode config.set_string( "network-frag-mode", comboBoxFragMode->currentText().toAscii(), comboBoxFragMode->currentText().length() ); // ike frag not disabled if( comboBoxFragMode->currentIndex() ) { // max packet size config.set_number( "network-frag-size", lineEditFragSize->text().toLong() ); } // dead peer detection enabled if( !checkBoxDPD->isChecked() ) config.set_number( "network-dpd-enable", 0 ); else config.set_number( "network-dpd-enable", 1 ); // isakmp failure notifications enabled if( !checkBoxNotify->isChecked() ) config.set_number( "network-notify-enable", 0 ); else config.set_number( "network-notify-enable", 1 ); // login banner enabled if( !checkBoxBanner->isChecked() ) config.set_number( "client-banner-enable", 0 ); else config.set_number( "client-banner-enable", 1 ); // dns enabled if( !checkBoxDNSEnable->isChecked() ) { // disabled config.set_number( "client-dns-used", 0 ); } else { // enabled config.set_number( "client-dns-used", 1 ); // dns settings if( checkBoxDNSAuto->isChecked() ) { // automatic dns server addresses config.set_number( "client-dns-auto", 1 ); } else { // manual dns server addresses config.set_number( "client-dns-auto", 0 ); config.del( "client-dns-addr" ); QString DNSServer; DNSServer = lineEditDNSServer1->text(); DNSServer = DNSServer.replace( ' ', "" ); if( inet_addr( DNSServer.toAscii() ) ) config.add_string( "client-dns-addr", DNSServer.toAscii(), DNSServer.length() ); DNSServer = lineEditDNSServer2->text(); DNSServer = DNSServer.replace( ' ', "" ); if( inet_addr( DNSServer.toAscii() ) ) config.add_string( "client-dns-addr", DNSServer.toAscii(), DNSServer.length() ); DNSServer = lineEditDNSServer3->text(); DNSServer = DNSServer.replace( ' ', "" ); if( inet_addr( DNSServer.toAscii() ) ) config.add_string( "client-dns-addr", DNSServer.toAscii(), DNSServer.length() ); DNSServer = lineEditDNSServer4->text(); DNSServer = DNSServer.replace( ' ', "" ); if( inet_addr( DNSServer.toAscii() ) ) config.add_string( "client-dns-addr", DNSServer.toAscii(), DNSServer.length() ); } if( checkBoxSuffixAuto->isChecked() ) { // automatic dns domain suffix config.set_number( "client-dns-suffix-auto", 1 ); } else { // manual dns domain suffix config.set_number( "client-dns-suffix-auto", 0 ); config.del( "client-dns-suffix" ); config.set_string( "client-dns-suffix", lineEditDNSSuffix->text().toAscii(), lineEditDNSSuffix->text().length() ); } } // authentication mode switch( comboBoxAuthMethod->currentIndex() ) { case AUTH_HYBRID_RSA_XAUTH: config.set_string( "auth-method", "hybrid-rsa-xauth", strlen( "hybrid-rsa-xauth" ) ); break; case AUTH_HYBRID_GRP_XAUTH: config.set_string( "auth-method", "hybrid-rsa-xauth", strlen( "hybrid-grp-xauth" ) ); break; case AUTH_MUTUAL_RSA_XAUTH: config.set_string( "auth-method", "mutual-rsa-xauth", strlen( "mutual-rsa-xauth" ) ); break; case AUTH_MUTUAL_PSK_XAUTH: config.set_string( "auth-method", "mutual-psk-xauth", strlen( "mutual-psk-xauth" ) ); break; case AUTH_MUTUAL_RSA: config.set_string( "auth-method", "mutual-rsa", strlen( "mutual-rsa" ) ); break; case AUTH_MUTUAL_PSK: config.set_string( "auth-method", "mutual-psk", strlen( "mutual-psk" ) ); break; } // local identity type QString locid = comboBoxLocalIDType->currentText(); if( !locid.compare( IDTXT_NONE ) ) config.set_string( "ident-client-type", "none", strlen( "none" ) ); if( !locid.compare( IDTXT_ASN1 ) ) config.set_string( "ident-client-type", "asn1dn", strlen( "asn1dn" ) ); if( !locid.compare( IDTXT_FQDN ) ) config.set_string( "ident-client-type", "fqdn", strlen( "fqdn" ) ); if( !locid.compare( IDTXT_UFQDN ) ) config.set_string( "ident-client-type", "ufqdn", strlen( "ufqdn" ) ); if( !locid.compare( IDTXT_ADDR ) ) config.set_string( "ident-client-type", "address", strlen( "address" ) ); if( !locid.compare( IDTXT_KEYID ) ) config.set_string( "ident-client-type", "keyid", strlen( "keyid" ) ); // local identity data if( lineEditLocalIDData->isEnabled() ) config.set_string( "ident-client-data", lineEditLocalIDData->text().toAscii(), lineEditLocalIDData->text().length() ); else config.del( "ident-client-data" ); // remote identity type QString rmtid = comboBoxRemoteIDType->currentText(); if( !rmtid.compare( IDTXT_ANY ) ) config.set_string( "ident-server-type", "any", strlen( "any" ) ); if( !rmtid.compare( IDTXT_ASN1 ) ) config.set_string( "ident-server-type", "asn1dn", strlen( "asn1dn" ) ); if( !rmtid.compare( IDTXT_FQDN ) ) config.set_string( "ident-server-type", "fqdn", strlen( "fqdn" ) ); if( !rmtid.compare( IDTXT_UFQDN ) ) config.set_string( "ident-server-type", "ufqdn", strlen( "ufqdn" ) ); if( !rmtid.compare( IDTXT_ADDR ) ) config.set_string( "ident-server-type", "address", strlen( "address" ) ); if( !rmtid.compare( IDTXT_KEYID ) ) config.set_string( "ident-server-type", "keyid", strlen( "keyid" ) ); // remote identity data if( lineEditRemoteIDData->isEnabled() ) config.set_string( "ident-server-data", lineEditRemoteIDData->text().toAscii(), lineEditRemoteIDData->text().length() ); else config.del( "ident-server-data" ); // credentials if( pathCAFile.size() ) { config.set_string( "auth-server-cert-name", lineEditCAName->text().toAscii(), lineEditCAName->text().length() ); BDATA fileData; fileData.file_load( pathCAFile.toAscii() ); config.set_binary( "auth-server-cert-data", fileData ); } else { if( lineEditCAName->text().isEmpty() ) { config.del( "auth-server-cert-name" ); config.del( "auth-server-cert-data" ); } } if( pathCertFile.size() ) { config.set_string( "auth-client-cert-name", lineEditCertName->text().toAscii(), lineEditCertName->text().length() ); BDATA fileData; fileData.file_load( pathCertFile.toAscii() ); config.set_binary( "auth-client-cert-data", fileData ); } else { if( lineEditCertName->text().isEmpty() ) { config.del( "auth-client-cert-name" ); config.del( "auth-client-cert-data" ); } } if( pathPKeyFile.size() ) { config.set_string( "auth-client-key-name", lineEditPKeyName->text().toAscii(), lineEditPKeyName->text().length() ); BDATA fileData; fileData.file_load( pathPKeyFile.toAscii() ); config.set_binary( "auth-client-key-data", fileData ); } else { if( lineEditPKeyName->text().isEmpty() ) { config.del( "auth-client-key-name" ); config.del( "auth-client-key-data" ); } } if( lineEditPSK->isEnabled() ) { BDATA psk; psk.set( ( const char * ) lineEditPSK->text().toAscii(), lineEditPSK->text().length() ); config.set_binary( "auth-mutual-psk", psk ); } else config.del( "auth-mutual-psk" ); // phase1 exchange type if( comboBoxP1Exchange->currentIndex() == EXCH_AGGR_MODE ) config.set_string( "phase1-exchange", "aggressive", strlen( "aggressive" ) ); if( comboBoxP1Exchange->currentIndex() == EXCH_MAIN_MODE ) config.set_string( "phase1-exchange", "main", strlen( "main" ) ); // phase1 dh group QString string; long dhgrp; string = comboBoxP1DHGroup->currentText(); string_to_dhgrp( string, dhgrp ); config.set_number( "phase1-dhgroup", dhgrp ); // phase1 cipher algorithm config.set_string( "phase1-cipher", comboBoxP1Cipher->currentText().toAscii(), comboBoxP1Cipher->currentText().length() ); // phase1 cipher key length config.set_number( "phase1-keylen", comboBoxP1Keylen->currentText().toLong() ); // phase1 hash algorithm config.set_string( "phase1-hash", comboBoxP1Hash->currentText().toAscii(), comboBoxP1Hash->currentText().length() ); // phase1 key life time config.set_number( "phase1-life-secs", lineEditP1LifeTime->text().toLong() ); // phase1 key life data config.set_number( "phase1-life-kbytes", lineEditP1LifeData->text().toLong() ); // phase1 Checkpoint vendor option if( !checkBoxCheckpointID->isChecked() ) config.set_number( "vendor-chkpt-enable", 0 ); else config.set_number( "vendor-chkpt-enable", 1 ); // phase2 trasform algorithm config.set_string( "phase2-transform", comboBoxP2Transform->currentText().toAscii(), comboBoxP2Transform->currentText().length() ); // phase2 transform key length config.set_number( "phase2-keylen", comboBoxP2Keylen->currentText().toLong() ); // phase2 hmac algorithm config.set_string( "phase2-hmac", comboBoxP2HMAC->currentText().toAscii(), comboBoxP2HMAC->currentText().length() ); // phase2 pfs group string = comboBoxP2PFSGroup->currentText(); string_to_dhgrp( string, dhgrp ); config.set_number( "phase2-pfsgroup", dhgrp ); // phase2 key life time config.set_number( "phase2-life-secs", lineEditP2LifeTime->text().toLong() ); // phase2 key life data config.set_number( "phase2-life-kbytes", lineEditP2LifeData->text().toLong() ); // ipcomp transform algorithm config.set_string( "ipcomp-transform", comboBoxP2Compress->currentText().toAscii(), comboBoxP2Compress->currentText().length() ); // policy level option config.set_string( "policy-level", comboBoxPolicyLevel->currentText().toAscii(), comboBoxPolicyLevel->currentText().length() ); // policy nailed sa option if( !checkBoxPolicyNailed->isChecked() ) config.set_number( "policy-nailed", 0 ); else config.set_number( "policy-nailed", 1 ); if( checkBoxPolicyAuto->isChecked() ) { // automatic config.set_number( "policy-list-auto", 1 ); } else { // manual config.set_number( "policy-list-auto", 0 ); config.del( "policy-list-include" ); config.del( "policy-list-exclude" ); // topology entries QTreeWidgetItem * rootItem = treeWidgetPolicies->invisibleRootItem(); long count = rootItem->childCount(); long index = 0; for( ; index < count; index++ ) { QTreeWidgetItem * i = rootItem->child( index ); // policy type if( i->type() == TREE_INCLUDE ) { // include config.add_string( "policy-list-include", i->text( 0 ).toAscii(), i->text( 0 ).length() ); } if( i->type() == TREE_EXCLUDE ) { // exlcude config.add_string( "policy-list-exclude", i->text( 0 ).toAscii(), i->text( 0 ).length() ); } } } return true; } bool _qikeaSite::verify() { QString errmsg; // check remote host if( lineEditHost->text().length() < 1 ) errmsg = "Please enter a valid host name or ip address."; // local adapter mode QString amode = comboBoxAddressMethod->currentText(); if( !amode.compare( AMTXT_VIRTUAL ) || !amode.compare( AMTXT_RANDOM ) ) { // adapter mtu if( ( lineEditMTU->text().toLong() < 68 ) || ( lineEditMTU->text().toLong() > 1500 ) ) errmsg = "Please enter valid Adapter MTU from 68 to 1500 bytes."; // adapter address if( !checkBoxAddressAuto->isChecked() ) { // adapter address QString Address = lineEditAddress->text(); Address = Address.replace( ' ', "" ); uint32_t addr = inet_addr( Address.toAscii() ); if( !addr || ( addr == INADDR_NONE ) ) errmsg = "Please enter valid virtual adapter address."; // adapter netmask QString Netmask = lineEditNetmask->text(); Netmask = Netmask.replace( ' ', "" ); uint32_t mask = inet_addr( Netmask.toAscii() ); if( !mask ) errmsg = "Please enter valid virtual adapter netmask."; } } // dns enabled if( checkBoxDNSEnable->isChecked() ) { // dns settings if( !checkBoxDNSAuto->isChecked() ) { // manual dns server addresses QString DNSServer; uint32_t addr; DNSServer = lineEditDNSServer1->text(); DNSServer = DNSServer.replace( ' ', "" ); addr = inet_addr( DNSServer.toAscii() ); if( addr && ( addr == INADDR_NONE ) ) errmsg = "Please enter valid DNS server #1 address."; DNSServer = lineEditDNSServer2->text(); DNSServer = DNSServer.replace( ' ', "" ); if( addr && ( addr == INADDR_NONE ) ) errmsg = "Please enter valid DNS server #2 address."; DNSServer = lineEditDNSServer3->text(); DNSServer = DNSServer.replace( ' ', "" ); if( addr && ( addr == INADDR_NONE ) ) errmsg = "Please enter valid DNS server #3 address."; DNSServer = lineEditDNSServer4->text(); DNSServer = DNSServer.replace( ' ', "" ); if( addr && ( addr == INADDR_NONE ) ) errmsg = "Please enter valid DNS server #4 address."; } if( !checkBoxSuffixAuto->isChecked() ) { // manual dns domain suffix QString DNSSuffix = lineEditDNSSuffix->text(); if( !DNSSuffix.length() ) errmsg = "Please enter valid DNS suffix."; } } // check local id data bool isaddr_l = ( comboBoxLocalIDType->currentText().compare( IDTXT_ADDR ) == 0 ); if( isaddr_l && lineEditLocalIDData->isEnabled() ) if( lineEditLocalIDData->text().length() < 1 ) errmsg = "Please enter valid local ID address data."; // check remote id data bool isaddr_r = ( comboBoxRemoteIDType->currentText().compare( IDTXT_ADDR ) == 0 ); if( isaddr_r && lineEditRemoteIDData->isEnabled() ) if( lineEditRemoteIDData->text().length() < 1 ) errmsg = "Please enter valid remote ID address data."; // check cert authority file if( toolButtonCAFile->isEnabled() ) if( lineEditCAName->text().length() < 1 ) errmsg = "Please enter valid certificate authority file path."; // check cert file if( toolButtonCertFile->isEnabled() ) if( lineEditCertName->text().length() < 1 ) errmsg = "Please enter valid certificate file path."; // check private key file if( toolButtonPKeyFile->isEnabled() ) if( lineEditPKeyName->text().length() < 1 ) errmsg = "Please enter valid private key file path."; // check pre shared key if( lineEditPSK->isEnabled() ) if( lineEditPSK->text().length() < 1 ) errmsg = "Please enter valid pre-shared key."; // verify policy list /* if( !checkBoxPolicyAuto->isChecked() ) if( !treeWidgetPolicies->childCount() ) errmsg = "You must specify at least one remote network resource."; */ if( errmsg.length() ) { QMessageBox m; m.critical( this, "Site Configuration Error", errmsg, QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton ); return false; } if( comboBoxP1Exchange->currentIndex() == EXCH_MAIN_MODE ) { if( !isaddr_l || !isaddr_r ) { long index = comboBoxAuthMethod->currentIndex(); if( ( index == AUTH_MUTUAL_PSK_XAUTH ) || ( index == AUTH_MUTUAL_PSK ) ) { QMessageBox m; m.warning( this, "Site Configuration Warning", "Main mode and Pre-Shared Keys should be used with Address " "ID types. While some gateways require alternate ID types, " "use them with caution.", QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton ); } } } // accept the dialog changes accept(); return true; } void _qikeaSite::updateConfigMethod() { updateGeneral( true, true ); } void _qikeaSite::updateAddressMethod() { updateGeneral( false, true ); } void _qikeaSite::updateAddressAuto() { updateGeneral( false, false ); } void _qikeaSite::updateGeneral( bool adflt, bool mdflt ) { QString amode = comboBoxAddressMethod->currentText(); // auto configuration long aconf = comboBoxConfigMethod->currentIndex(); switch( aconf ) { case 0: // disabled comboBoxAddressMethod->setEnabled( true ); comboBoxAddressMethod->clear(); comboBoxAddressMethod->addItem( QString( AMTXT_VIRTUAL ) ); comboBoxAddressMethod->addItem( AMTXT_RANDOM ); comboBoxAddressMethod->addItem( AMTXT_DIRECT ); break; case 3: // dhcp over ipsec comboBoxAddressMethod->setEnabled( true ); comboBoxAddressMethod->clear(); comboBoxAddressMethod->addItem( AMTXT_VIRTUAL ); break; default: // push or pull comboBoxAddressMethod->setEnabled( true ); comboBoxAddressMethod->clear(); comboBoxAddressMethod->addItem( AMTXT_VIRTUAL ); comboBoxAddressMethod->addItem( AMTXT_DIRECT ); break; } combobox_setbytext( amode, comboBoxAddressMethod ); if( amode != comboBoxAddressMethod->currentText() ) mdflt = true; // adapter mode if( !amode.compare( AMTXT_VIRTUAL ) || !amode.compare( AMTXT_RANDOM ) ) { switch( aconf ) { case 0: // autoconf disabled checkBoxAddressAuto->setEnabled( false ); checkBoxAddressAuto->setChecked( false ); if( mdflt ) { if( !amode.compare( AMTXT_VIRTUAL ) ) { lineEditAddress->setText( "0.0.0.0" ); lineEditNetmask->setText( "255.255.255.0" ); } if( !amode.compare( AMTXT_RANDOM ) ) { lineEditAddress->setText( "198.18.0.0" ); lineEditNetmask->setText( "255.254.0.0" ); } } break; case 1: // ike config push case 2: // ike config pull checkBoxAddressAuto->setEnabled( true ); if( mdflt ) { checkBoxAddressAuto->setChecked( true ); lineEditAddress->setText( "0.0.0.0" ); lineEditNetmask->setText( "255.255.255.0" ); } break; case 3: // dhcp over ipsec checkBoxAddressAuto->setEnabled( false ); checkBoxAddressAuto->setChecked( true ); if( mdflt ) { lineEditAddress->setText( "0.0.0.0" ); lineEditNetmask->setText( "0.0.0.0" ); } break; } textLabelAddress->setEnabled( true ); textLabelNetmask->setEnabled( true ); if( checkBoxAddressAuto->isChecked() ) { lineEditAddress->setEnabled( false ); lineEditNetmask->setEnabled( false ); } else { lineEditAddress->setEnabled( true ); lineEditNetmask->setEnabled( true ); } } else { // direct checkBoxAddressAuto->setEnabled( false ); textLabelAddress->setEnabled( false ); textLabelNetmask->setEnabled( false ); lineEditAddress->setEnabled( false ); lineEditNetmask->setEnabled( false ); } updateClient(); updateNameResolution(); } void _qikeaSite::updateClient() { long aconf = comboBoxConfigMethod->currentIndex(); // nat traversal mode if( !comboBoxNATTMode->currentIndex() ) { // disabled textLabelNATTPort->setEnabled( false ); lineEditNATTPort->setEnabled( false ); textLabelNATTRate->setEnabled( false ); lineEditNATTRate->setEnabled( false ); textLabelNATTSecs->setEnabled( false ); } else { // not disabled textLabelNATTPort->setEnabled( true ); lineEditNATTPort->setEnabled( true ); textLabelNATTRate->setEnabled( true ); lineEditNATTRate->setEnabled( true ); textLabelNATTSecs->setEnabled( true ); } // ike frag mode if( !comboBoxFragMode->currentIndex() ) { // disabled textLabelFragSize->setEnabled( false ); lineEditFragSize->setEnabled( false ); } else { // not disabled textLabelFragSize->setEnabled( true ); lineEditFragSize->setEnabled( true ); } // login banner if( aconf == 0 ) { checkBoxBanner->setEnabled( false ); checkBoxBanner->setChecked( false ); } else checkBoxBanner->setEnabled( true ); } void _qikeaSite::updateNameResolution() { long aconf = comboBoxConfigMethod->currentIndex(); // dns enabled if( checkBoxDNSEnable->isChecked() ) { // enabled if( aconf == 0 ) { checkBoxDNSAuto->setEnabled( false ); checkBoxDNSAuto->setChecked( false ); checkBoxSuffixAuto->setEnabled( false ); checkBoxSuffixAuto->setChecked( false ); } else { checkBoxDNSAuto->setEnabled( true ); checkBoxSuffixAuto->setEnabled( true ); } textLabelDNSServer1->setEnabled( true ); textLabelDNSServer2->setEnabled( true ); textLabelDNSServer3->setEnabled( true ); textLabelDNSServer4->setEnabled( true ); if( checkBoxDNSAuto->isChecked() ) { lineEditDNSServer1->setEnabled( false ); lineEditDNSServer2->setEnabled( false ); lineEditDNSServer3->setEnabled( false ); lineEditDNSServer4->setEnabled( false ); } else { lineEditDNSServer1->setEnabled( true ); lineEditDNSServer2->setEnabled( true ); lineEditDNSServer3->setEnabled( true ); lineEditDNSServer4->setEnabled( true ); } textLabelDNSSuffix->setEnabled( true ); if( checkBoxSuffixAuto->isChecked() ) lineEditDNSSuffix->setEnabled( false ); else lineEditDNSSuffix->setEnabled( true ); } else { // disabled checkBoxDNSAuto->setEnabled( false ); textLabelDNSServer1->setEnabled( false ); textLabelDNSServer2->setEnabled( false ); textLabelDNSServer3->setEnabled( false ); textLabelDNSServer4->setEnabled( false ); lineEditDNSServer1->setEnabled( false ); lineEditDNSServer2->setEnabled( false ); lineEditDNSServer3->setEnabled( false ); lineEditDNSServer4->setEnabled( false ); checkBoxSuffixAuto->setEnabled( false ); textLabelDNSSuffix->setEnabled( false ); lineEditDNSSuffix->setEnabled( false ); } } void _qikeaSite::updateAuthMethod() { // authentication method long auth = comboBoxAuthMethod->currentIndex(); switch( auth ) { case AUTH_HYBRID_RSA_XAUTH: case AUTH_HYBRID_GRP_XAUTH: { comboBoxLocalIDType->clear(); // comboBoxLocalIDType->addItem( IDTXT_NONE ); comboBoxLocalIDType->addItem( IDTXT_FQDN ); comboBoxLocalIDType->addItem( IDTXT_UFQDN ); comboBoxLocalIDType->addItem( IDTXT_ADDR ); comboBoxLocalIDType->addItem( IDTXT_KEYID ); break; } case AUTH_MUTUAL_RSA_XAUTH: case AUTH_MUTUAL_RSA: { comboBoxLocalIDType->clear(); comboBoxLocalIDType->addItem( IDTXT_ASN1 ); comboBoxLocalIDType->addItem( IDTXT_FQDN ); comboBoxLocalIDType->addItem( IDTXT_UFQDN ); comboBoxLocalIDType->addItem( IDTXT_ADDR ); comboBoxLocalIDType->addItem( IDTXT_KEYID ); break; } case AUTH_MUTUAL_PSK_XAUTH: case AUTH_MUTUAL_PSK: { comboBoxLocalIDType->clear(); comboBoxLocalIDType->addItem( IDTXT_FQDN ); comboBoxLocalIDType->addItem( IDTXT_UFQDN ); comboBoxLocalIDType->addItem( IDTXT_ADDR ); comboBoxLocalIDType->addItem( IDTXT_KEYID ); break; } } switch( auth ) { case AUTH_HYBRID_RSA_XAUTH: case AUTH_HYBRID_GRP_XAUTH: case AUTH_MUTUAL_RSA_XAUTH: case AUTH_MUTUAL_RSA: { comboBoxRemoteIDType->clear(); comboBoxRemoteIDType->addItem( IDTXT_ANY ); comboBoxRemoteIDType->addItem( IDTXT_ASN1 ); comboBoxRemoteIDType->addItem( IDTXT_FQDN ); comboBoxRemoteIDType->addItem( IDTXT_UFQDN ); comboBoxRemoteIDType->addItem( IDTXT_ADDR ); comboBoxRemoteIDType->addItem( IDTXT_KEYID ); break; } case AUTH_MUTUAL_PSK_XAUTH: case AUTH_MUTUAL_PSK: { comboBoxRemoteIDType->clear(); comboBoxRemoteIDType->addItem( IDTXT_ANY ); comboBoxRemoteIDType->addItem( IDTXT_FQDN ); comboBoxRemoteIDType->addItem( IDTXT_UFQDN ); comboBoxRemoteIDType->addItem( IDTXT_ADDR ); comboBoxRemoteIDType->addItem( IDTXT_KEYID ); break; } } } void _qikeaSite::updateAuthentication() { // grab the current local and remote id types QString locid = comboBoxLocalIDType->currentText(); QString rmtid = comboBoxRemoteIDType->currentText(); // update the authentication method updateAuthMethod(); // attempt to re-select the id types if( !combobox_setbytext( locid, comboBoxLocalIDType ) ) { lineEditLocalIDData->clear(); checkBoxLocalIDOption->setChecked( true ); } if( !combobox_setbytext( rmtid, comboBoxRemoteIDType ) ) { lineEditRemoteIDData->clear(); checkBoxRemoteIDOption->setChecked( true ); } // authentication credentials switch( comboBoxAuthMethod->currentIndex() ) { case AUTH_HYBRID_RSA_XAUTH: { lineEditCAName->setEnabled( true ); toolButtonCAFile->setEnabled( true ); lineEditCertName->setEnabled( false ); toolButtonCertFile->setEnabled( false ); lineEditPKeyName->setEnabled( false ); toolButtonPKeyFile->setEnabled( false ); lineEditPSK->setEnabled( false ); break; } case AUTH_HYBRID_GRP_XAUTH: { lineEditCAName->setEnabled( true ); toolButtonCAFile->setEnabled( true ); lineEditCertName->setEnabled( false ); toolButtonCertFile->setEnabled( false ); lineEditPKeyName->setEnabled( false ); toolButtonPKeyFile->setEnabled( false ); lineEditPSK->setEnabled( true ); break; } case AUTH_MUTUAL_RSA_XAUTH: case AUTH_MUTUAL_RSA: { lineEditCAName->setEnabled( true ); toolButtonCAFile->setEnabled( true ); lineEditCertName->setEnabled( true ); toolButtonCertFile->setEnabled( true ); lineEditPKeyName->setEnabled( true ); toolButtonPKeyFile->setEnabled( true ); lineEditPSK->setEnabled( false ); break; } case AUTH_MUTUAL_PSK_XAUTH: case AUTH_MUTUAL_PSK: { lineEditCAName->setEnabled( false ); toolButtonCAFile->setEnabled( false ); lineEditCertName->setEnabled( false ); toolButtonCertFile->setEnabled( false ); lineEditPKeyName->setEnabled( false ); toolButtonPKeyFile->setEnabled( false ); lineEditPSK->setEnabled( true ); break; } } updateLocalID(); updateRemoteID(); } void _qikeaSite::updateLocalID() { QString type = comboBoxLocalIDType->currentText(); if( !type.compare( IDTXT_NONE ) ) { textLabelLocalIDData->setText( "" ); lineEditLocalIDData->setEnabled( false ); checkBoxLocalIDOption->setHidden( true ); return; } if( !type.compare( IDTXT_ASN1 ) ) { textLabelLocalIDData->setText( "ASN.1 DN String" ); checkBoxLocalIDOption->setHidden( false ); checkBoxLocalIDOption->setText( "Use the subject in the client certificate" ); } if( !type.compare( IDTXT_FQDN ) ) { textLabelLocalIDData->setText( "FQDN String" ); checkBoxLocalIDOption->setHidden( true ); } if( !type.compare( IDTXT_UFQDN ) ) { textLabelLocalIDData->setText( "UFQDN String" ); checkBoxLocalIDOption->setHidden( true ); } if( !type.compare( IDTXT_ADDR ) ) { textLabelLocalIDData->setText( "Address String" ); checkBoxLocalIDOption->setHidden( false ); checkBoxLocalIDOption->setText( "Use discovered local host address" ); } if( !type.compare( IDTXT_KEYID ) ) { textLabelLocalIDData->setText( "Key ID String" ); checkBoxLocalIDOption->setHidden( true ); } if( checkBoxLocalIDOption->isHidden() ) lineEditLocalIDData->setEnabled( true ); else lineEditLocalIDData->setEnabled( !checkBoxLocalIDOption->isChecked() ); } void _qikeaSite::updateRemoteID() { QString type = comboBoxRemoteIDType->currentText(); if( !type.compare( IDTXT_ANY ) ) { textLabelRemoteIDData->setText( "" ); lineEditRemoteIDData->setEnabled( false ); checkBoxRemoteIDOption->setHidden( true ); return; } if( !type.compare( IDTXT_ASN1 ) ) { textLabelRemoteIDData->setText( "ASN.1 DN String" ); checkBoxRemoteIDOption->setHidden( false ); checkBoxRemoteIDOption->setText( "Use the subject in the received certificate" ); } if( !type.compare( IDTXT_FQDN ) ) { textLabelRemoteIDData->setText( "FQDN String" ); checkBoxRemoteIDOption->setHidden( true ); } if( !type.compare( IDTXT_UFQDN ) ) { textLabelRemoteIDData->setText( "UFQDN String" ); checkBoxRemoteIDOption->setHidden( true ); } if( !type.compare( IDTXT_ADDR ) ) { textLabelRemoteIDData->setText( "Address String" ); checkBoxRemoteIDOption->setHidden( false ); checkBoxRemoteIDOption->setText( "Use discovered remote host address" ); } if( !type.compare( IDTXT_KEYID ) ) { textLabelRemoteIDData->setText( "Key ID String" ); checkBoxRemoteIDOption->setHidden( true ); } if( checkBoxRemoteIDOption->isHidden() ) lineEditRemoteIDData->setEnabled( true ); else lineEditRemoteIDData->setEnabled( !checkBoxRemoteIDOption->isChecked() ); } void _qikeaSite::updatePhase1() { // exchange mode if( comboBoxP1Exchange->currentIndex() == EXCH_AGGR_MODE ) { // aggressive mode ( auto not allowed ) QString text = comboBoxP1DHGroup->currentText(); comboBoxP1DHGroup->clear(); comboBoxP1DHGroup->addItem( "group 1" ); comboBoxP1DHGroup->addItem( "group 2" ); comboBoxP1DHGroup->addItem( "group 5" ); comboBoxP1DHGroup->addItem( "group 14" ); comboBoxP1DHGroup->addItem( "group 15" ); combobox_setbytext( text, comboBoxP1DHGroup ); } if( comboBoxP1Exchange->currentIndex() == EXCH_MAIN_MODE ) { // main mode ( auto allowed ) QString text = comboBoxP1DHGroup->currentText(); comboBoxP1DHGroup->clear(); comboBoxP1DHGroup->addItem( "auto" ); comboBoxP1DHGroup->addItem( "group 1" ); comboBoxP1DHGroup->addItem( "group 2" ); comboBoxP1DHGroup->addItem( "group 5" ); comboBoxP1DHGroup->addItem( "group 14" ); comboBoxP1DHGroup->addItem( "group 15" ); combobox_setbytext( text, comboBoxP1DHGroup ); } // chipher type QString text = comboBoxP1Keylen->currentText(); switch( comboBoxP1Cipher->currentIndex() ) { case 1: // aes { comboBoxP1Keylen->setEnabled( true ); comboBoxP1Keylen->clear(); comboBoxP1Keylen->addItem( "auto" ); comboBoxP1Keylen->addItem( "128" ); comboBoxP1Keylen->addItem( "192" ); comboBoxP1Keylen->addItem( "256" ); break; } case 2: // blowfish { comboBoxP1Keylen->setEnabled( true ); comboBoxP1Keylen->clear(); comboBoxP1Keylen->addItem( "auto" ); for( long b = 128; b <= 256; b += 8 ) comboBoxP1Keylen->addItem( QString::number( b, 10 ) ); break; } default: // all others { comboBoxP1Keylen->setCurrentIndex( 0 ); comboBoxP1Keylen->setEnabled( false ); break; } } if( !comboBoxP1Cipher->currentIndex() ) comboBoxP1Keylen->setCurrentIndex( 0 ); else combobox_setbytext( text, comboBoxP1Keylen ); updateAuthentication(); } void _qikeaSite::updatePhase2() { // transform type QString text = comboBoxP2Keylen->currentText(); switch( comboBoxP2Transform->currentIndex() ) { case 1: // aes { comboBoxP2Keylen->setEnabled( true ); comboBoxP2Keylen->clear(); comboBoxP2Keylen->addItem( "auto" ); comboBoxP2Keylen->addItem( "128" ); comboBoxP2Keylen->addItem( "192" ); comboBoxP2Keylen->addItem( "256" ); break; } case 2: // blowfish { comboBoxP2Keylen->setEnabled( true ); comboBoxP2Keylen->clear(); comboBoxP2Keylen->addItem( "auto" ); for( long b = 128; b <= 256; b += 8 ) comboBoxP2Keylen->addItem( QString::number( b, 10 ) ); break; } default: // all others { comboBoxP2Keylen->setCurrentIndex( 0 ); comboBoxP2Keylen->setEnabled( false ); break; } } if( !comboBoxP2Transform->currentIndex() ) comboBoxP2Keylen->setCurrentIndex( 0 ); else combobox_setbytext( text, comboBoxP2Keylen ); } void _qikeaSite::updatePolicy() { // policy configuration if( checkBoxPolicyAuto->isChecked() ) { // automatic treeWidgetPolicies->setEnabled( false ); pushButtonPolicyAdd->setEnabled( false ); pushButtonPolicyMod->setEnabled( false ); pushButtonPolicyDel->setEnabled( false ); } else { // manual treeWidgetPolicies->setEnabled( true ); pushButtonPolicyAdd->setEnabled( true ); // policy item selection if( treeWidgetPolicies->currentItem() != NULL ) { // have selection pushButtonPolicyMod->setEnabled( true ); pushButtonPolicyDel->setEnabled( true ); } else { // no selection pushButtonPolicyMod->setEnabled( false ); pushButtonPolicyDel->setEnabled( false ); } } } void _qikeaSite::selectLocalID() { lineEditLocalIDData->clear(); checkBoxLocalIDOption->setChecked( true ); updateLocalID(); } void _qikeaSite::selectRemoteID() { lineEditRemoteIDData->clear(); checkBoxRemoteIDOption->setChecked( true ); updateRemoteID(); } void _qikeaSite::inputCAFile() { QString types( "OpenSSL Files (*.key *.pem *.crt *.crt);;" "PKCS #12 Files (*.p12 *.pfx);;" "All files (*)" ); QString filePath = QFileDialog::getOpenFileName( this, "Select CA File", QDir::homePath(), types ); if( filePath.length() ) { pathCAFile = filePath; QFileInfo fileInfo( filePath ); lineEditCAName->setText( fileInfo.fileName() ); } } void _qikeaSite::inputCertFile() { QString types( "OpenSSL Files (*.key *.pem *.crt *.crt);;" "PKCS #12 Files (*.p12 *.pfx);;" "All files (*)" ); QString filePath = QFileDialog::getOpenFileName( this, "Select CA File", QDir::homePath(), types ); if( filePath.length() ) { pathCertFile = filePath; QFileInfo fileInfo( filePath ); lineEditCertName->setText( fileInfo.fileName() ); } } void _qikeaSite::inputPKeyFile() { QString types( "OpenSSL Files (*.key *.pem *.crt *.crt);;" "PKCS #12 Files (*.p12 *.pfx);;" "All files (*)" ); QString filePath = QFileDialog::getOpenFileName( this, "Select CA File", QDir::homePath(), types ); if( filePath.length() ) { pathPKeyFile = filePath; QFileInfo fileInfo( filePath ); lineEditPKeyName->setText( fileInfo.fileName() ); } } ike-2.2.1+dfsg/source/qikea/site.ui000066400000000000000000002405701223036517100171100ustar00rootroot00000000000000 Shrew Soft Inc. qikeaSite Qt::ApplicationModal 0 0 318 376 0 0 VPN Site Configuration :/png/site_mod.png:/png/site_mod.png true false true 0 0 0 General Remote Host Host Name or IP Address false 1 0 Port false 0 0 50 16777215 500 Qt::AlignRight Auto Configuration false disabled ike config pull ike config push dhcp over ipsec Local Host Address Method false Use a virtual adapter and assigned address Use a virtual adapter and random address Use an existing adapter and current address Qt::Vertical 20 40 MTU false 50 16777215 1380 Qt::AlignRight Qt::Horizontal QSizePolicy::Preferred 20 20 Obtain Automatically true 0 0 Address Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false false 0 0 009 . 009 . 009 . 009; 0 . 0 . 0 . 0 Qt::AlignHCenter 0 0 Netmask Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false false 0 0 009 . 009 . 009 . 009; 0 . 0 . 0 . 0 Qt::AlignHCenter Qt::Vertical 20 61 Client Firewall Options false NAT Traversal false false 0 disable enable force-draft force-rfc force-cisco-udp false NAT Traversal Port false false 0 0 50 16777215 4500 Qt::AlignRight false Keep-Alive Packet Rate false false 0 0 50 16777215 15 Qt::AlignRight false 0 0 Secs false IKE Fragmentation false 1 disable enable force Maximum Packet Size false 0 0 50 16777215 Qt::RightToLeft 540 0 0 Bytes false Other Options Enable Dead Peer Detection true Enable IKSAMP Failure Notifications true Enable Client Login Banner true Qt::Vertical 20 291 NameResolution Enable DNS true Obtain Automatically true Server Address #1 false false 0 0 009 . 009 . 009 . 009; 0 . 0 . 0 . 0 Qt::AlignHCenter Server Address #2 false false 0 0 009 . 009 . 009 . 009; 0 . 0 . 0 . 0 Qt::AlignHCenter Server Address #3 false false 0 0 009 . 009 . 009 . 009; 0 . 0 . 0 . 0 Qt::AlignHCenter Server Address #4 false false 0 0 009 . 009 . 009 . 009; 0 . 0 . 0 . 0 Qt::AlignHCenter Obtain Automatically true DNS Suffix false false 0 0 Qt::Vertical 20 40 Authentication Authentication Method false Hybrid RSA + XAuth Hybrid GRP + XAuth Mutual RSA + XAuth Mutual PSK + XAuth Mutual RSA Mutual PSK 0 Local Identity Identification Type false ASN.1 Distinguished Name Fully Qualified Domain Name User Fully Qualified Domain Name IP Address Key Identifier Identification Data false false Obtain Identification Automatically true Qt::Vertical 20 40 Remote Identity Identification Type false Any ASN.1 Distinguished Name Fully Qualified Domain Name User Fully Qualified Domain Name IP Address Key Identifier Identification Data false false Identification Option true Qt::Vertical 20 40 Credentials Server Certificate Authority File false true true ... Client Certificate File false true true ... Client Private Key File false true true true ... Pre Shared Key false QLineEdit::Password Qt::Vertical 254 20 Qt::Vertical 278 16 Phase 1 Proposal Parameters 0 0 Exchange Type false aggressive main 0 0 DH Exchange false auto group 1 group 2 group 5 group 14 group 15 group 16 group 17 group 18 0 0 Cipher Algorithm false auto aes blowfish 3des des cast 0 0 Cipher Key Length false false auto 128 136 144 152 160 168 176 184 192 200 208 216 224 232 240 248 256 Bits false 0 0 Hash Algorithm false auto sha1 md5 sha2-256 sha2-384 sha2-512 0 0 Key Life Time Limit false 0 0 50 16777215 86400 Qt::AlignRight 0 0 Secs false 0 0 Key Life Data Limit false 0 0 50 16777215 0 Qt::AlignRight KBs false Enable Check Point Compatible Vendor ID false Qt::Vertical 21 101 Phase 2 Proposal Parameters Transform Algorithm false auto esp-aes esp-blowfish esp-3des esp-des esp-cast Transform Key Length false false auto 128 136 144 152 160 168 176 184 192 200 208 216 224 232 240 248 256 Bits false HMAC Algorithm false auto sha1 md5 sha2-256 sha2-384 sha2-512 PFS Exchange false disabled auto group 1 group 2 group 5 group 14 group 15 group 16 group 17 group 18 Compression Algorithm false disabled deflate Key Life Time Limit false 0 0 50 16777215 3600 Qt::AlignRight Secs false Key Life Data Limit false 0 0 50 16777215 0 Qt::AlignRight KBs false Qt::Vertical 20 81 Policy IPsec Policy Configuration Policy Generation Level false auto require unique shared Maintain Persistent Security Associations false false Obtain Topology Automatically or Tunnel All true false Remote Network Resources false 0 0 Add false 0 0 Modify false 0 0 Delete Qt::Horizontal QSizePolicy::Expanding 20 20 &Save Alt+S true true &Cancel true tabWidget lineEditHost lineEditPort comboBoxConfigMethod comboBoxAddressMethod checkBoxAddressAuto lineEditMTU lineEditAddress lineEditNetmask comboBoxNATTMode lineEditNATTPort lineEditNATTRate comboBoxFragMode lineEditFragSize checkBoxDPD checkBoxNotify checkBoxBanner checkBoxDNSEnable checkBoxDNSAuto lineEditDNSServer1 lineEditDNSServer2 lineEditDNSServer3 lineEditDNSServer4 checkBoxSuffixAuto lineEditDNSSuffix comboBoxAuthMethod tabWidgetAuthInfo comboBoxLocalIDType lineEditLocalIDData checkBoxLocalIDOption comboBoxRemoteIDType lineEditRemoteIDData checkBoxRemoteIDOption lineEditCAName toolButtonCAFile lineEditCertName toolButtonCertFile lineEditPKeyName toolButtonPKeyFile lineEditPSK comboBoxP1Exchange comboBoxP1DHGroup comboBoxP1Cipher comboBoxP1Keylen comboBoxP1Hash lineEditP1LifeTime lineEditP1LifeData checkBoxCheckpointID comboBoxP2Transform comboBoxP2Keylen comboBoxP2HMAC comboBoxP2PFSGroup comboBoxP2Compress lineEditP2LifeTime lineEditP2LifeData comboBoxPolicyLevel checkBoxPolicyNailed checkBoxPolicyAuto treeWidgetPolicies pushButtonPolicyAdd pushButtonPolicyMod pushButtonPolicyDel buttonSave buttonCancel ike-2.2.1+dfsg/source/qikea/topology.cpp000066400000000000000000000066621223036517100201670ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "qikea.h" bool _qikeaTopology::verify() { QString Address = lineEditAddress->text(); Address = Address.replace( ' ', "" ); QString Netmask = lineEditNetmask->text(); Netmask = Netmask.replace( ' ', "" ); in_addr_t addr = ntohl( inet_addr( Address.toAscii() ) ); in_addr_t mask = ntohl( inet_addr( Netmask.toAscii() ) ); // verify the netmask if( ( mask != 0 ) && ( mask != ( in_addr_t ) ~0 ) ) { long count = 31; long bitset = 31; long bitclr = 0; while( count >= 0 ) { if( ( mask >> count ) & 1 ) bitset = count; else bitclr = count; if( bitclr > bitset ) { // error QMessageBox m; m.critical( this, "Topology Entry Error", "The network mask you have specified is invalid.", QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton ); return false; } count--; } } // verify the address if( addr & ~mask ) { // warning QMessageBox m; m.warning( this, "Topology Entry Warning", "The network address is not valid for the given network mask.\n" "An acceptable value has been substituted.", QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton ); in_addr inaddr; inaddr.s_addr = htonl( addr & mask ); lineEditAddress->setText( inet_ntoa( inaddr ) ); return false; } // call the dialog accept function accept(); return true; } ike-2.2.1+dfsg/source/qikea/topology.ui000066400000000000000000000107451223036517100200170ustar00rootroot00000000000000 qikeaTopology 0 0 192 153 Tolology Entry :/png/site_mod.png:/png/site_mod.png Type false Include Exclude Address false 0 0 009 . 009 . 009 . 009; 0 . 0 . 0 . 0 Qt::AlignHCenter Netmask false 0 0 009 . 009 . 009 . 009; 0 . 0 . 0 . 0 Qt::AlignHCenter Qt::Vertical 20 40 Qt::Horizontal QSizePolicy::Expanding 41 31 &Ok Alt+O true true &Cancel true ike-2.2.1+dfsg/source/qikec/000077500000000000000000000000001223036517100155775ustar00rootroot00000000000000ike-2.2.1+dfsg/source/qikec/CMakeLists.txt000066400000000000000000000057241223036517100203470ustar00rootroot00000000000000# # Shrew Soft VPN / Client Connect Application # Cross Platform Make File # # author : Matthew Grooms # : mgrooms@shrew.net # : Copyright 2007, Shrew Soft Inc # include_directories( ${IKE_SOURCE_DIR}/source/ ${IKE_SOURCE_DIR}/source/ikec ${IKE_SOURCE_DIR}/source/iked ${IKE_SOURCE_DIR}/source/libike ${IKE_SOURCE_DIR}/source/libidb ${IKE_SOURCE_DIR}/source/libith ${IKE_SOURCE_DIR}/source/liblog ${IKE_SOURCE_DIR}/source/libip ${QT_INCLUDES} ) link_directories( ${IKE_SOURCE_DIR}/source/libip ${QT_LIBRARY_DIR} ) include( ${QT_USE_FILE} ) qt4_wrap_ui( UIH_FILES banner.ui filepass.ui root.ui ) qt4_wrap_cpp( CXX_FILES qikec.h ) qt4_add_resources( QRC_FILES qikec.qrc ) add_executable( qikec main.cpp qikec.cpp root.cpp ${UIH_FILES} ${CXX_FILES} ${QRC_FILES} ) target_link_libraries( qikec ss_ike ss_idb ss_ith ss_log crypto pthread ${QT_LIBRARIES} ) if( APPLE ) set( MACOSX_BUNDLE_BUNDLE_NAME "Shrew Soft VPN Client Connect" ) set( MACOSX_BUNDLE_GUI_IDENTIFIER "net.shrew.vpn.qikec" ) set( MACOSX_BUNDLE_ICON_FILE "qikec.icns" ) set( MACOSX_BUNDLE_LONG_VERSION_STRING ${RELVER} ) set( MACOSX_BUNDLE_SHORT_VERSION_STRING ${RELVER} ) set_property( TARGET qikec PROPERTY MACOSX_BUNDLE ON ) set_property( TARGET qikec PROPERTY OUTPUT_NAME ${MACOSX_BUNDLE_BUNDLE_NAME} ) add_custom_target( qikec-bundle-resources COMMAND mkdir -p ${CMAKE_CURRENT_SOURCE_DIR}/${MACOSX_BUNDLE_BUNDLE_NAME}.app/Contents/Resources COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/png/${MACOSX_BUNDLE_ICON_FILE} ${CMAKE_CURRENT_SOURCE_DIR}/${MACOSX_BUNDLE_BUNDLE_NAME}.app/Contents/Resources/${MACOSX_BUNDLE_ICON_FILE} ) add_dependencies( qikec ProjectName qikec-bundle-resources ) endif( APPLE ) install( TARGETS qikec RUNTIME DESTINATION bin BUNDLE DESTINATION "/Applications" ) install( FILES qikec.1 DESTINATION ${PATH_MAN}/man1 ) if( APPLE ) # set( # MACOSX_BUNDLE_DEST_DIR # "/Applications/${MACOSX_BUNDLE_BUNDLE_NAME}.app" ) # set( # MACOSX_QTPLUGINS_DEST_DIR # "${MACOSX_BUNDLE_DEST_DIR}/Contents/MacOS/plugins" ) # install( # DIRECTORY "${QT_PLUGINS_DIR}/imageformats" # DESTINATION "${MACOSX_QTPLUGINS_DEST_DIR}" # COMPONENT Runtime ) # set( # MACOSX_QTCONF_DEST_DIR # "${MACOSX_BUNDLE_DEST_DIR}/Contents/Resources" ) # install( # CODE "file( WRITE \"${MACOSX_QTCONF_DEST_DIR}/qt.conf\" \"\" )" # COMPONENT Runtime ) install( CODE "execute_process( COMMAND \"install_name_tool\" -change ${QT_LIBRARY_DIR}/QtCore.framework/Versions/4/QtCore ShrewSoftQtCore.framework/Versions/4/ShrewSoftQtCore \"/Applications/${MACOSX_BUNDLE_BUNDLE_NAME}.app/Contents/MacOS/${MACOSX_BUNDLE_BUNDLE_NAME}\" )" ) install( CODE "execute_process( COMMAND \"install_name_tool\" -change ${QT_LIBRARY_DIR}/QtGui.framework/Versions/4/QtGui ShrewSoftQtGui.framework/Versions/4/ShrewSoftQtGui \"/Applications/${MACOSX_BUNDLE_BUNDLE_NAME}.app/Contents/MacOS/${MACOSX_BUNDLE_BUNDLE_NAME}\" )" ) endif( APPLE ) ike-2.2.1+dfsg/source/qikec/banner.ui000066400000000000000000000040101223036517100173760ustar00rootroot00000000000000 ikecBanner 0 0 340 204 Login Banner :/png/png/ikec.png Qt::Horizontal QSizePolicy::Expanding 386 16 Qt::ApplicationModal 0 0 32767 20 &OK true true buttonOk textBrowserMOTD ike-2.2.1+dfsg/source/qikec/filepass.ui000066400000000000000000000061551223036517100177530ustar00rootroot00000000000000 ikecFilePass Qt::ApplicationModal 0 0 249 88 File Password :/png/png/ikec.png QFrame::NoFrame QFrame::Plain Please enter the file password false QLineEdit::Password Qt::Horizontal QSizePolicy::Expanding 52 20 0 0 32767 20 &OK true true 0 0 32767 20 &Cancel true ike-2.2.1+dfsg/source/qikec/main.cpp000066400000000000000000000051021223036517100172250ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "qikec.h" QIKEC qikec; int main( int argc, char ** argv ) { signal( SIGPIPE, SIG_IGN ); // init the app QApplication a( argc, argv ); // create our root window qikecRoot r; // init our ikec object qikec.init( argc, argv, &r ); // show the root window r.show(); // autoconnect if requested if( qikec.auto_connect() ) qikec.vpn_connect( false ); // connect application close signal to slot a.connect( &a, SIGNAL( lastWindowClosed() ), &a, SLOT( quit() ) ); return a.exec(); } ike-2.2.1+dfsg/source/qikec/png/000077500000000000000000000000001223036517100163635ustar00rootroot00000000000000ike-2.2.1+dfsg/source/qikec/png/ikec.png000066400000000000000000000066571223036517100200220ustar00rootroot00000000000000PNG  IHDR@@iqsRGBbKGD pHYsu0u03rtIME4οS /IDATxytU?%URCE5(@VmqH8*[uzڦ-ΰEeMu@$ *7Hg YHN{} ?o bN@ P T$0;0( :@#P-f?ILV)  B̰":g)*jm(.À(Z̮!h U*4S'9m4qQ &_\Z J8u.RZQ~ 8l1J`Q'/=IB@4Y[j%I tK0Mo",qȅӭU4ӗp:]g4 F#[5jU좹S9e4r0(D$*E:e/sŀ`0z: ",٠Vjnqph&K$}L3 x,cvr.cy{p8\l޺0#)u8_*Ӂe]5_hp ccH!H \KhnqtT[9r{ iSfsԅOl!I. *͛CALT5uM455#2^>’j+kc{3 x6ɌڶܫޖH hQ]O {%<4fIv'Z6;sg'T2X:o* $!xG'►ݥwg[oGNo̷FavB{# ]9 1mgAdw3"6YIy |F@W<ɍe7Ew-Fb|4dSH}B'E]?tV7}HaIˍXCI4Jw2u/=ԫv%WHA4jU+,-)`4)I=8GF 9I*"‚zV٥c=M& Ώ[<|}3Yy>j2=H,j~J%ycz=NdʽVzK<\[A?% fOxy^d]-;ƞja9>FD3,۹*j9u~-WWp=^:{yg8;N]Irx{O{QVYח No?Yy/xdy* L(vaAXO)|ο0fToώ2OgǶOhc/w0{F"rV&%Ʊ85l|{MWzidm&/adɋo|L߾L^LT<1K?egCulzn%ߦev|CuL4񽿦-;X)5 ڶ[MoO]YV=/.@m?,ic-P(5Xӯ۞4zd{RZ^ >JѠh:Z }fH6k,Is7Cw)sżߛȽuD}mcn2ښȹ)9YC#ɰ;h~7\_ѕi ;A8'nVw='CJNJwP>ߗnR0 @$D@AqOЃai4alQ =aq#=3kibv9fgzROQ?yTV܉h5nbv=?x4 A/{7:CrR?B~JO{hk3ANg.=9B'=$UrE2a$Miy ]=Fz7${,EWYruPi[ȣ2t]ݖP*[wHVqܳ(QY_AXr"N4A U4p,<;A~Q%2ARͳ5Kw]-fhXN* TfLͧO025my lyj"ď".& RAqY b*q>$Ig;k,pv8d2"‚5m Oci$&>Oc_3ZP*T4PU̎qB>"vK{6 h1 Fӛh~*tZztiGZVö}IP $IUmegS{ f[ u VjI?{'#ɐ$WÎ/kBR0jkxp`3ynz4a$ #/$RJnDNn5ux $|)8 ~Rb7\ч*rr %Ib/Fվȭv/ST6pI"xޔm^ Qͺm Zj1_hdFU5 բ|֗$.>ldkb” h{}ldSXRu X'Z_Ŧ 耍2iũSr+9|ŕh1ۛ4>A UdYDEoI-!)1xBf-j?e] n#%9\>hN>Wǿtm\a"ֆGE_2Iq7t8g_SZQ{`7LtA ^T*s&(ϝBrR<+m$#3/=˵ŠR˵[2EA.W*s"BuI ̞"‚|\Kj$p*3is8]ims@@O96D f\B,cˆ APdmBQi5.%UQY]_p<a`HyBZ4xZ'JBըd;.Ş`'U'Z-:Us5?ҏ4( bCxIENDB`ike-2.2.1+dfsg/source/qikec/png/qikec.icns000066400000000000000000000573111223036517100203440ustar00rootroot00000000000000icns^it32!!!!JWrW/!!:n伈a.!!]̚v9!!CΠp,!!aA!!]I!!F4!!*^!!I)!!d?!!(gJ!!'uG!!'nD!!WyK1!!FQO!!)AdK!!/=aI!!.8EDQځY!!05[5tY!!-1W1Y!!+.;;H؅/!!',9a{a,S,a!!%)z l))Q)"!!#']ɼ45Ʌ]&!!&ɄN&A&\3&$!!#$?րM$1hh1$vM$$"!!"#hZ#Z1>օZ#!!"0>u0"!!t!t!!KY!!=/!!f!!=!!/ȖY!!YY!!Y!!KY!!t!Ր/!!fK!!=!!Ȁ/!f!!=/!fK!=!!f!/!!/f!KՋ/!!K=!f!! t/KՅ!YY!/t!!t!K!K=!ՌY!!tt!tf!t!Yt=!!=t!=/ȁ!Y/!f!!!Մ!/!Y!!K!tK!KK!/!!K=/!!!!!=t=Y!!Y/t!!"Y"g"!!"Y">"!!#Z#֮#"!!$@[[$#!!&&i&$!!'B'֐B'$!!(kk(׫(%!!(*E8z*&!!),G,T,&!!)/pp/c/$!!(1>>>1"!!&3M3Y31!!6h6͉\6/!!3:FF::kk:*!!-==ma=anzn=$!!%AXdAMA;!!;EEPЅE.!!0IIkIF#!!GMyXM9!!3QQQ'!!NUuuU>!!6ZZoZW$!!O_!!&fvQ!!2v|_!!3|Ãp'!!4v'!!6{(!!7k(!!)`!!lJ!!D2!!*~b!!H+!!_6!!bA!!N|8!!-iי]!!.`ƕG!!.VۉpH!!=X/!!!9999]iiE99P~ÑÕrD99oҚƄN99WӠC99rU99n\99ZJ99Ao99]@99uS99?w^99?[99>~X99jQ99X|F99Ezn99itV99Mnk<99bhP99Ica99R^G99Zdb99@Uu^99EQr\99DNYYdށk99FKmKk99DGiGk99BEPP\܅E99>CNrrCfCr99=@ą |@@d@:99:>nJJυn=99=Αa=U=mI=;99;<Tڀ`V>ېV>;99?{{?۫?<99?AYMÔA=99AC[CfC=99@EEtE<99?GSRŔSG:99=I`IkIG99LyL҉nLF99JOZZȅOO{{OA99DRR}rRr}}R<9999bhhS99Lll~lh<99bqQ99@quf99UzvA99iS99>vDžc99HŊq99IÐ>99J?99K?99M{@99@q99|^99XI99As99\B99pK99sV99bɋM99Dyۤn99Dq̕[99Eh߉Ǘ\99RjE999iiiiņriizёѮriiݚԢyiiޠΟqiiȦ~iiɪii®uiio’iinii}iiniimiimii{iisiirÚiiĖiixőkiiƍ{iiuljii}ȆtiiÂ؈iiniir{攄iirýiisvviiqtt„iipr{{riimpyppiilo҅ Ҝoooiijmvvۅmiilڬl~lulkiijk~чkttkkkjiijjǃs}jiis|Ї좫siiiiiǓii|riiii|iirږiiiiiiiiiriiii|iiڀriii|rii|iiǔirǛiirǁirii|iii riirЍiiii|iiiiiЁi|ii|iDŽ|rǃځiriiiidžЁiriiiiiㅃirii|riiiЎii||iiriiiiijj}jiikkkjiik~kjiilllkiimmmkiinnnliinoxҔoliinpppliinssskiint}|Ӕ}tjiilvvvtiixx݉ݑxsiivzނՅzz՛zoiiq||畃||kiil~~φ~zii{ȉ߅riis„kiiҎÇziiuʼnmiiŌ}iiwƐkii͓{iio˗ii~ʚoiiɟ}iimǣiitŧiiuëmiivmiiwniixniiniiiiµuiioȕiipii̫wiiɧii֧xiiqÜ云iiqؕϭiir԰ii|riiit8mk@ @pp@ P￀P0p0 p @@```P@0P@0 P@``pp``00pp0 p` `` p p` PP0 @@@@@@@@@@@@@@@@0 P@ `` pp ``  `P p`00`P``p```00 @@0 @@P@@@pp pp @߯@@PP@icnV Bike-2.2.1+dfsg/source/qikec/qikec.1000066400000000000000000000065731223036517100167700ustar00rootroot00000000000000.\" .\" Copyright (c) 2007 .\" Shrew Soft Inc. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" 3. Redistributions in any form must be accompanied by information on .\" how to obtain complete source code for the software and any .\" accompanying software that uses the software. The source code .\" must either be included in the distribution or be available for no .\" more than the cost of distribution plus a nominal fee, and must be .\" freely redistributable under reasonable conditions. For an .\" executable file, complete source code means the source code for all .\" modules it contains. It does not include source code for modules or .\" files that typically accompany the major components of the operating .\" system on which the executable file runs. .\" .\" THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS .\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED .\" WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR .\" NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC .\" 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. .\" .\" AUTHOR : Matthew Grooms .\" mgrooms@shrew.net .\" .\" .Dd April 12, 2010 .Dt QIKEC 1 .Os .Sh NAME .Nm qikec .Nd Internet Key Exchange Connect .Sh SYNOPSIS .Nm .Op Fl r Ar name .Op Fl u Ar username .Op Fl p Ar password .Op Fl a .Sh DESCRIPTION The .Nm Qt GUI application provides a simple interface for users to interact with .Xr iked 8 ( Shrew Soft IKE Daemon ). This interface allows a user to control an IPsec VPN Client connection with a remote gateway. The parameters used for the connection are described in a Site Configuration file. For more information about managing Site Configuration files, please see the .Xr ikea 1 man page. Please note, the ikec application is not typically started directly by a user but as a sub-process of the .Xr ikea 1 Qt GUI application. .Pp The options are as follows: .Bl -tag -width Fl .It Fl r Ar name Specify the Site Configuration name. .It Fl u Ar username Specify the Xauth username for the connection. .It Fl p Ar password Specify the Xauth password for the connection. .It Fl a Automatically initiate the connection. .El .Sh RETURN VALUES The command exits with 0 on success, and non-zero on errors. .Sh SEE ALSO .Xr iked 8 , .Xr ikec 1 , .Xr qikea 1 , .Sh HISTORY The .Nm program was written by Matthew Grooms ( mgrooms@shrew.net ) as part of the Shrew Soft ( http://www.shrew.net ) family of IPsec products. ike-2.2.1+dfsg/source/qikec/qikec.cpp000066400000000000000000000110611223036517100173760ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "qikec.h" const char * _QIKEC::app_name() { static const char name[] = "qikec"; return name; } bool _QIKEC::init( int argc, char ** argv, qikecRoot * setRoot ) { // store our root window r = setRoot; // load our command line options if( qikec.read_opts( argc, argv ) != OPT_RESULT_SUCCESS ) { r->lineEditUsername->setEnabled( false ); r->lineEditPassword->setEnabled( false ); r->pushButtonConnect->setEnabled( false ); qikec.show_help(); return false; } if( !qikec.config_load() ) { r->lineEditUsername->setEnabled( false ); r->lineEditPassword->setEnabled( false ); r->pushButtonConnect->setEnabled( false ); return false; } if( username.size() ) { username.add( "", 1 ); r->lineEditUsername->setText( username.text() ); } if( password.size() ) { password.add( "", 1 ); r->lineEditPassword->setText( password.text() ); } if( !user_credentials() ) r->groupBoxCredentials->hide(); return true; } bool _QIKEC::get_username() { TextData data; QApplication::postEvent( r, new UsernameEvent( &data ) ); while( data.result == -1 ) msleep( 10 ); if( !data.text.length() ) return false; username.del(); username.set( ( const char * ) data.text.toAscii(), data.text.length() ); return true; } bool _QIKEC::get_password() { TextData data; QApplication::postEvent( r, new PasswordEvent( &data ) ); while( data.result == -1 ) msleep( 10 ); if( !data.text.length() ) return false; password.del(); password.set( ( const char * ) data.text.toAscii(), data.text.length() ); return true; } bool _QIKEC::get_filepass( BDATA & path ) { log( STATUS_INFO, "file password required for %s\n", path.text() ); FilePassData PassData; PassData.filepath = path.text(); QApplication::postEvent( r, new FilePassEvent( &PassData ) ); while( PassData.result == -1 ) msleep( 10 ); if( PassData.result == QDialog::Rejected ) return false; QString text = PassData.password; fpass.del(); fpass.set( ( const char * ) text.toAscii(), text.length() ); return true; } bool _QIKEC::set_status( long status, BDATA * text ) { log( status, text->text() ); return true; } bool _QIKEC::set_stats() { QApplication::postEvent( r, new StatsEvent( stats ) ); return true; } bool _QIKEC::log( long code, const char * format, ... ) { char buff[ 1024 ]; memset( buff, 0, sizeof( buff ) ); va_list list; va_start( list, format ); vsnprintf( buff, sizeof( buff ), format, list ); QApplication::postEvent( r, new StatusEvent( buff, code ) ); return true; } ike-2.2.1+dfsg/source/qikec/qikec.h000066400000000000000000000123571223036517100170540ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #ifndef _QIKEC_H_ #define _QIKEC_H_ #include #include #include #include #include #include #include #include #include #include #include "client.h" #include "config.h" #include "ui_root.h" #include "ui_banner.h" #include "ui_filepass.h" #define EVENT_STATUS QEvent::Type( QEvent::User + 1 ) #define EVENT_STATE QEvent::Type( QEvent::User + 2 ) #define EVENT_STATS QEvent::Type( QEvent::User + 3 ) #define EVENT_USERNAME QEvent::Type( QEvent::User + 4 ) #define EVENT_PASSWORD QEvent::Type( QEvent::User + 5 ) #define EVENT_FILEPASS QEvent::Type( QEvent::User + 6 ) class StatusEvent : public QEvent { public: QString text; long status; StatusEvent( QString value, long level ) : QEvent( EVENT_STATUS ) { text = value; status = level; } }; class StatsEvent : public QEvent { public: IKEI_STATS stats; StatsEvent( IKEI_STATS value ) : QEvent( EVENT_STATS ) { stats = value; } }; class TextData { public: QString text; int result; TextData() { result = -1; } }; class UsernameEvent : public QEvent { public: TextData * data; UsernameEvent( TextData * value ) : QEvent( EVENT_USERNAME ) { data = value; } }; class PasswordEvent : public QEvent { public: TextData * data; PasswordEvent( TextData * value ) : QEvent( EVENT_PASSWORD ) { data = value; } }; class FilePassData { public: QString filepath; QString password; int result; FilePassData() { result = -1; } }; class FilePassEvent : public QEvent { public: FilePassData * data; FilePassEvent( FilePassData * value ) : QEvent( EVENT_FILEPASS ) { data = value; } }; typedef class _qikecRoot : public QMainWindow, public Ui::ikecRoot { Q_OBJECT public: _qikecRoot( QWidget * parent = NULL ) : QMainWindow( parent ) { setupUi( this ); connect( pushButtonConnect, SIGNAL( clicked() ), this, SLOT( siteConnect() ) ); connect( pushButtonExit, SIGNAL( clicked() ), this, SLOT( siteDisconnect() ) ); lineEditUsername->setFocus(); } public slots: void customEvent( QEvent * e ); void siteConnect(); void siteDisconnect(); }qikecRoot; typedef class _qikecBanner : public QDialog, public Ui::ikecBanner { Q_OBJECT public: _qikecBanner( QWidget * parent = NULL ) : QDialog( parent ) { setupUi( this ); connect( buttonOk, SIGNAL( clicked() ), this, SLOT( accept() ) ); } }qikecBanner; typedef class _qikecFilePass : public QDialog, public Ui::ikecFilePass { Q_OBJECT public: _qikecFilePass( QWidget * parent = NULL ) : QDialog( parent ) { setupUi( this ); connect( buttonOk, SIGNAL( clicked() ), this, SLOT( accept() ) ); connect( buttonCancel, SIGNAL( clicked() ), this, SLOT( reject() ) ); } }qikecFilePass; typedef class _QIKEC : public _CLIENT, public QThread { friend class _qikecRoot; protected: qikecRoot * r; public: const char * app_name(); bool get_username(); bool get_password(); bool get_filepass( BDATA & path ); bool set_stats(); bool set_status( long status, BDATA * text ); bool init( int argc, char ** argv, qikecRoot * setr ); bool log( long code, const char * format, ... ); }QIKEC; extern QIKEC qikec; #endif ike-2.2.1+dfsg/source/qikec/qikec.pro000066400000000000000000000010101223036517100174050ustar00rootroot00000000000000TEMPLATE = app LANGUAGE = C++ CONFIG += qt warn_on release QT += qtgui LIBS += ../ikea/.obj/config.o ../libidb/libidb.a ../libith/libith.a ../liblog/liblog.a ../libike/libike.so DEFINES += OPT_NATT UNIX INCLUDEPATH += ./ ./.. ../libidb/ ../libike/ ../iked/ ../libip/ ../liblog ../libith HEADERS = \ ikec.h SOURCES = \ ikec.cpp \ main.cpp \ root.cpp FORMS = \ banner.ui \ filepass.ui \ root.ui RESOUCES = \ ikec.qrc unix { UI_DIR = .ui MOC_DIR = .moc OBJECTS_DIR = .obj } ike-2.2.1+dfsg/source/qikec/qikec.qrc000066400000000000000000000001371223036517100174030ustar00rootroot00000000000000 png/ikec.png ike-2.2.1+dfsg/source/qikec/root.cpp000066400000000000000000000162011223036517100172660ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #include "qikec.h" void _qikecRoot::customEvent( QEvent * e ) { if( e->type() == EVENT_STATUS ) { StatusEvent * event = ( StatusEvent * ) e; switch( event->status ) { case STATUS_WARN: textBrowserStatus->setTextColor( QColor( 192, 128, 0 ) ); break; case STATUS_FAIL: textBrowserStatus->setTextColor( QColor( 128, 0, 0 ) ); break; default: textBrowserStatus->setTextColor( QColor( 0, 0, 0 ) ); } switch( event->status ) { case STATUS_BANNER: { qikecBanner b( this ); b.textBrowserMOTD->setText( event->text ); b.exec(); break; } case STATUS_DISCONNECTED: textLabelStatusValue->setText( "Disconnected" ); lineEditUsername->setEnabled( true ); lineEditPassword->setEnabled( true ); pushButtonConnect->setEnabled( true ); pushButtonConnect->setText( "Connect" ); pushButtonExit->setEnabled( true ); pushButtonExit->setText( "Exit" ); textBrowserStatus->insertPlainText( "tunnel disabled\n" ); break; case STATUS_CONNECTING: textLabelStatusValue->setText( "Connecting" ); lineEditUsername->setEnabled( false ); lineEditPassword->setEnabled( false ); pushButtonConnect->setEnabled( false ); pushButtonConnect->setText( "Connect" ); pushButtonExit->setEnabled( true ); pushButtonExit->setText( "Cancel" ); textBrowserStatus->insertPlainText( "bringing up tunnel ...\n" ); break; case STATUS_CONNECTED: textLabelStatusValue->setText( "Connected" ); pushButtonConnect->setEnabled( true ); pushButtonConnect->setText( "Disconnect" ); pushButtonExit->setEnabled( false ); pushButtonExit->setText( "Exit" ); textBrowserStatus->insertPlainText( "tunnel enabled\n" ); break; case STATUS_DISCONNECTING: textLabelStatusValue->setText( "Disconnecting" ); pushButtonConnect->setEnabled( false ); pushButtonConnect->setText( "Disconnect" ); pushButtonExit->setEnabled( false ); pushButtonExit->setText( "Exit" ); textBrowserStatus->insertPlainText( "bringing down tunnel ...\n" ); break; case STATUS_INFO: case STATUS_WARN: case STATUS_FAIL: textBrowserStatus->insertPlainText( event->text ); break; default: textBrowserStatus->insertPlainText( "!!! unknown status message !!!\n" ); } textBrowserStatus->moveCursor( QTextCursor::End ); } if( e->type() == EVENT_STATS ) { StatsEvent * event = ( StatsEvent * ) e; QString n; n.setNum( event->stats.sa_good ); textLabelEstablishedValue->setText( n ); n.setNum( event->stats.sa_dead ); textLabelExpiredValue->setText( n ); n.setNum( event->stats.sa_fail ); textLabelFailedValue->setText( n ); textLabelRemoteValue->setText( inet_ntoa( event->stats.peer.saddr4.sin_addr ) ); switch( event->stats.natt ) { case IPSEC_NATT_NONE: textLabelTransportValue->setText( "IKE | ESP" ); break; case IPSEC_NATT_CISCO: textLabelTransportValue->setText( "IKE | CISCO-UDP / ESP" ); break; case IPSEC_NATT_V00: textLabelTransportValue->setText( "NAT-T v00 / IKE | ESP" ); break; case IPSEC_NATT_V01: textLabelTransportValue->setText( "NAT-T v01 / IKE | ESP" ); break; case IPSEC_NATT_V02: textLabelTransportValue->setText( "NAT-T v02 / IKE | ESP" ); break; case IPSEC_NATT_V03: textLabelTransportValue->setText( "NAT-T v03 / IKE | ESP" ); break; case IPSEC_NATT_RFC: textLabelTransportValue->setText( "NAT-T RFC / IKE | ESP" ); break; } if( event->stats.frag ) textLabelFragValue->setText( "Enabled" ); else textLabelFragValue->setText( "Disabled" ); if( event->stats.dpd ) textLabelDPDValue->setText( "Enabled" ); else textLabelDPDValue->setText( "Disabled" ); } if( e->type() == EVENT_USERNAME ) { UsernameEvent * event = ( UsernameEvent * ) e; event->data->text = lineEditUsername->text(); event->data->result = 0; } if( e->type() == EVENT_PASSWORD ) { PasswordEvent * event = ( PasswordEvent * ) e; event->data->text = lineEditPassword->text(); event->data->result = 0; lineEditPassword->clear(); } if( e->type() == EVENT_FILEPASS ) { FilePassEvent * event = ( FilePassEvent * ) e; qikecFilePass fp; QFileInfo pathInfo( event->data->filepath ); fp.setWindowTitle( "Password for " + pathInfo.fileName() ); event->data->result = fp.exec(); event->data->password = fp.lineEditPassword->text(); } } void _qikecRoot::siteConnect() { if( qikec.state() != CLIENT_STATE_DISCONNECTED ) { // call ikec disconnect function qikec.vpn_disconnect(); } else { // verify that a valid username and password was supplied if( !groupBoxCredentials->isHidden() ) { if( !lineEditUsername->text().length() || !lineEditPassword->text().length() ) { qikec.log( STATUS_FAIL, "please enter a valid username and password\n" ); return; } } // call ikec connect function qikec.vpn_connect( false ); } } void _qikecRoot::siteDisconnect() { if( qikec.state() != CLIENT_STATE_DISCONNECTED ) { // call ikec disconnect function qikec.vpn_disconnect(); } else { // close the application close(); } } ike-2.2.1+dfsg/source/qikec/root.ui000066400000000000000000000322361223036517100171270ustar00rootroot00000000000000 ikecRoot 0 0 296 299 Shrew Soft VPN Connect :/png/png/ikec.png 0 Connect false Credentials Username false Password false QLineEdit::Password 0 0 0 0 Qt::Horizontal QSizePolicy::MinimumExpanding 71 17 true Connect true true Exit Network GroupBox :/png/png/ikec.png Qt::AlignCenter Qt::Vertical 20 40 Established - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false 0 false Expired - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false 0 false Failed - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false 0 false Qt::Vertical 20 40 GroupBox Status - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false Disconnected false Remote Host - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false false Transport Used - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false false IKE Fragmentation - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false false Dead Peer Detection - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false false lineEditUsername lineEditPassword pushButtonConnect pushButtonExit tabWidget textBrowserStatus ike-2.2.1+dfsg/source/test_ith/000077500000000000000000000000001223036517100163265ustar00rootroot00000000000000ike-2.2.1+dfsg/source/test_ith/CMakeLists.txt000066400000000000000000000006211223036517100210650ustar00rootroot00000000000000# # Shrew Soft VPN / IKE Daemon # Cross Platform Make File # # author : Matthew Grooms # : mgrooms@shrew.net # : Copyright 2007, Shrew Soft Inc # include_directories( ${IKE_SOURCE_DIR}/source ${IKE_SOURCE_DIR}/source/libith ) link_directories( ${IKE_SOURCE_DIR}/source/libith ) add_executable( test_ith_timer main.cpp ) target_link_libraries( test_ith_timer ss_ith pthread ) ike-2.2.1+dfsg/source/test_ith/main.cpp000066400000000000000000000100221223036517100177510ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #ifdef WIN32 # define _CRT_SECURE_NO_DEPRECATE #endif #include "time.h" #include "libith.h" ITH_TIMER timer; // // utility functions // char * tstamp( char * str, long len ) { time_t ctime; struct tm * ltime; time( &ctime ); ltime = localtime( &ctime ); strftime( str, len, "%H:%M:%S", ltime ); return str; } // // test event class // typedef class _EVENT_TEST : public ITH_EVENT { public: _EVENT_TEST( long set_id ); long id; bool func(); void add( ITH_TIMER & add_timer, long add_delay ); void end(); }EVENT_TEST; _EVENT_TEST::_EVENT_TEST( long set_id ) { id = set_id; } bool _EVENT_TEST::func() { end(); return false; } void _EVENT_TEST::add( ITH_TIMER & add_timer, long add_delay ) { delay = add_delay; add_timer.add( this ); char str[ 50 ]; printf( "%s : event %i added\n", tstamp( str, 50 ), id ); } void _EVENT_TEST::end() { char str[ 50 ]; printf( "%s : event %i executed\n", tstamp( str, 50 ), id ); } // // test helper thread // typedef class _TEST_EXEC : public ITH_EXEC { protected: long func( void * arg ); }TEST_EXEC; long _TEST_EXEC::func( void * arg ) { char str[ 50 ]; printf( "%s : --- THREAD RUN ---\n", tstamp( str, 50 ) ); Sleep( 1000 ); EVENT_TEST test1( 1 ); test1.add( timer, 5000 ); EVENT_TEST test2( 2 ); test2.add( timer, 1000 ); EVENT_TEST test3( 3 ); test3.add( timer, 8000 ); Sleep( 11000 ); timer.end(); printf( "%s : --- THREAD RUN ---\n", tstamp( str, 50 ) ); return 0; } // // test program // int main( int argc, char * argv[], char * envp[] ) { char str[ 50 ]; printf( "%s : ==== TEST RUN ====\n", tstamp( str, 50 ) ); TEST_EXEC exec; exec.exec( NULL ); timer.run(); printf( "%s : ==== TEST END ====\n", tstamp( str, 50 ) ); printf( "press to continue ...\n", tstamp( str, 50 ) ); getchar(); return 0; } ike-2.2.1+dfsg/source/version.h000066400000000000000000000043611223036517100163450ustar00rootroot00000000000000 /* * Copyright (c) 2007 * Shrew Soft Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the software and any * accompanying software that uses the software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY SHREW SOFT INC ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL SHREW SOFT INC * 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. * * AUTHOR : Matthew Grooms * mgrooms@shrew.net * */ #define CLIENT_VER_MAJ 2 #define CLIENT_VER_MIN 2 #define CLIENT_VER_BLD 1 #define CLIENT_RELEASE 1 #define CLIENT_YEAR 2013